hanami 1.3.5 → 2.0.0.alpha4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +196 -5
  3. data/FEATURES.md +1 -3
  4. data/README.md +4 -4
  5. data/hanami.gemspec +27 -30
  6. data/lib/hanami/application/autoloader/inflector_adapter.rb +22 -0
  7. data/lib/hanami/application/container/boot/inflector.rb +7 -0
  8. data/lib/hanami/application/container/boot/logger.rb +7 -0
  9. data/lib/hanami/application/container/boot/rack_logger.rb +19 -0
  10. data/lib/hanami/application/container/boot/rack_monitor.rb +12 -0
  11. data/lib/hanami/application/container/boot/routes_helper.rb +9 -0
  12. data/lib/hanami/application/container/boot/settings.rb +7 -0
  13. data/lib/hanami/application/router.rb +59 -0
  14. data/lib/hanami/application/routes.rb +55 -0
  15. data/lib/hanami/application/routes_helper.rb +34 -0
  16. data/lib/hanami/application/routing/middleware/stack.rb +89 -0
  17. data/lib/hanami/application/routing/resolver/node.rb +50 -0
  18. data/lib/hanami/application/routing/resolver/trie.rb +59 -0
  19. data/lib/hanami/application/routing/resolver.rb +87 -0
  20. data/lib/hanami/application/settings/dotenv_store.rb +60 -0
  21. data/lib/hanami/application/settings.rb +93 -0
  22. data/lib/hanami/application.rb +349 -174
  23. data/lib/hanami/assets/application_configuration.rb +63 -0
  24. data/lib/hanami/assets/configuration.rb +54 -0
  25. data/lib/hanami/boot.rb +5 -0
  26. data/lib/hanami/cli/application/cli.rb +40 -0
  27. data/lib/hanami/cli/application/command.rb +47 -0
  28. data/lib/hanami/cli/application/commands/console.rb +81 -0
  29. data/lib/hanami/cli/application/commands.rb +16 -0
  30. data/lib/hanami/cli/base_command.rb +48 -0
  31. data/lib/hanami/cli/commands/command.rb +23 -31
  32. data/lib/hanami/cli/commands/server.rb +63 -14
  33. data/lib/hanami/cli/commands.rb +5 -41
  34. data/lib/hanami/configuration/logger.rb +40 -0
  35. data/lib/hanami/configuration/middleware.rb +9 -29
  36. data/lib/hanami/configuration/null_configuration.rb +14 -0
  37. data/lib/hanami/configuration/router.rb +52 -0
  38. data/lib/hanami/configuration/sessions.rb +50 -0
  39. data/lib/hanami/configuration.rb +152 -185
  40. data/lib/hanami/init.rb +5 -0
  41. data/lib/hanami/server.rb +5 -69
  42. data/lib/hanami/setup.rb +8 -2
  43. data/lib/hanami/slice.rb +167 -0
  44. data/lib/hanami/version.rb +3 -1
  45. data/lib/hanami/web/rack_logger.rb +96 -0
  46. data/lib/hanami.rb +42 -241
  47. metadata +88 -222
  48. data/bin/hanami +0 -6
  49. data/lib/hanami/action/csrf_protection.rb +0 -211
  50. data/lib/hanami/action/routing_helpers.rb +0 -40
  51. data/lib/hanami/app.rb +0 -96
  52. data/lib/hanami/application_configuration.rb +0 -1495
  53. data/lib/hanami/application_name.rb +0 -108
  54. data/lib/hanami/application_namespace.rb +0 -14
  55. data/lib/hanami/assets/asset.rb +0 -72
  56. data/lib/hanami/assets/static.rb +0 -102
  57. data/lib/hanami/cli/commands/assets/precompile.rb +0 -42
  58. data/lib/hanami/cli/commands/assets.rb +0 -16
  59. data/lib/hanami/cli/commands/console.rb +0 -95
  60. data/lib/hanami/cli/commands/db/apply.rb +0 -32
  61. data/lib/hanami/cli/commands/db/console.rb +0 -44
  62. data/lib/hanami/cli/commands/db/create.rb +0 -32
  63. data/lib/hanami/cli/commands/db/drop.rb +0 -32
  64. data/lib/hanami/cli/commands/db/migrate.rb +0 -39
  65. data/lib/hanami/cli/commands/db/prepare.rb +0 -32
  66. data/lib/hanami/cli/commands/db/rollback.rb +0 -59
  67. data/lib/hanami/cli/commands/db/version.rb +0 -32
  68. data/lib/hanami/cli/commands/db.rb +0 -32
  69. data/lib/hanami/cli/commands/destroy/action.rb +0 -137
  70. data/lib/hanami/cli/commands/destroy/app.rb +0 -159
  71. data/lib/hanami/cli/commands/destroy/mailer.rb +0 -74
  72. data/lib/hanami/cli/commands/destroy/migration.rb +0 -51
  73. data/lib/hanami/cli/commands/destroy/model.rb +0 -84
  74. data/lib/hanami/cli/commands/destroy.rb +0 -26
  75. data/lib/hanami/cli/commands/generate/action/action.erb +0 -7
  76. data/lib/hanami/cli/commands/generate/action/action_spec.minitest.erb +0 -11
  77. data/lib/hanami/cli/commands/generate/action/action_spec.rspec.erb +0 -9
  78. data/lib/hanami/cli/commands/generate/action/action_without_view.erb +0 -7
  79. data/lib/hanami/cli/commands/generate/action/view.erb +0 -7
  80. data/lib/hanami/cli/commands/generate/action/view_spec.minitest.erb +0 -12
  81. data/lib/hanami/cli/commands/generate/action/view_spec.rspec.erb +0 -10
  82. data/lib/hanami/cli/commands/generate/action.rb +0 -321
  83. data/lib/hanami/cli/commands/generate/app/application.erb +0 -313
  84. data/lib/hanami/cli/commands/generate/app/favicon.ico +0 -0
  85. data/lib/hanami/cli/commands/generate/app/gitkeep.erb +0 -0
  86. data/lib/hanami/cli/commands/generate/app/layout.erb +0 -7
  87. data/lib/hanami/cli/commands/generate/app/layout_spec.minitest.erb +0 -10
  88. data/lib/hanami/cli/commands/generate/app/layout_spec.rspec.erb +0 -10
  89. data/lib/hanami/cli/commands/generate/app/routes.erb +0 -5
  90. data/lib/hanami/cli/commands/generate/app/template.erb.erb +0 -10
  91. data/lib/hanami/cli/commands/generate/app/template.haml.erb +0 -7
  92. data/lib/hanami/cli/commands/generate/app/template.slim.erb +0 -8
  93. data/lib/hanami/cli/commands/generate/app.rb +0 -243
  94. data/lib/hanami/cli/commands/generate/mailer/mailer.erb +0 -9
  95. data/lib/hanami/cli/commands/generate/mailer/mailer_spec.minitest.erb +0 -7
  96. data/lib/hanami/cli/commands/generate/mailer/mailer_spec.rspec.erb +0 -5
  97. data/lib/hanami/cli/commands/generate/mailer.rb +0 -104
  98. data/lib/hanami/cli/commands/generate/migration/migration.erb +0 -4
  99. data/lib/hanami/cli/commands/generate/migration.rb +0 -41
  100. data/lib/hanami/cli/commands/generate/model/entity.erb +0 -2
  101. data/lib/hanami/cli/commands/generate/model/entity_spec.minitest.erb +0 -5
  102. data/lib/hanami/cli/commands/generate/model/entity_spec.rspec.erb +0 -3
  103. data/lib/hanami/cli/commands/generate/model/migration.erb +0 -10
  104. data/lib/hanami/cli/commands/generate/model/repository.erb +0 -5
  105. data/lib/hanami/cli/commands/generate/model/repository_spec.minitest.erb +0 -5
  106. data/lib/hanami/cli/commands/generate/model/repository_spec.rspec.erb +0 -3
  107. data/lib/hanami/cli/commands/generate/model.rb +0 -125
  108. data/lib/hanami/cli/commands/generate/secret.rb +0 -48
  109. data/lib/hanami/cli/commands/generate.rb +0 -28
  110. data/lib/hanami/cli/commands/new/.env.development.erb +0 -3
  111. data/lib/hanami/cli/commands/new/.env.test.erb +0 -3
  112. data/lib/hanami/cli/commands/new/.gitkeep.erb +0 -0
  113. data/lib/hanami/cli/commands/new/Gemfile.erb +0 -57
  114. data/lib/hanami/cli/commands/new/README.md.erb +0 -33
  115. data/lib/hanami/cli/commands/new/config/boot.erb +0 -2
  116. data/lib/hanami/cli/commands/new/config/environment.erb +0 -49
  117. data/lib/hanami/cli/commands/new/config.ru.erb +0 -3
  118. data/lib/hanami/cli/commands/new/gitignore.erb +0 -4
  119. data/lib/hanami/cli/commands/new/gitignore_with_sqlite.erb +0 -5
  120. data/lib/hanami/cli/commands/new/hanamirc.erb +0 -3
  121. data/lib/hanami/cli/commands/new/lib/project.erb +0 -2
  122. data/lib/hanami/cli/commands/new/minitest/Rakefile.erb +0 -12
  123. data/lib/hanami/cli/commands/new/minitest/features_helper.erb +0 -11
  124. data/lib/hanami/cli/commands/new/minitest/spec_helper.erb +0 -7
  125. data/lib/hanami/cli/commands/new/rspec/Rakefile.erb +0 -9
  126. data/lib/hanami/cli/commands/new/rspec/capybara.erb +0 -8
  127. data/lib/hanami/cli/commands/new/rspec/features_helper.erb +0 -12
  128. data/lib/hanami/cli/commands/new/rspec/rspec.erb +0 -2
  129. data/lib/hanami/cli/commands/new/rspec/spec_helper.erb +0 -103
  130. data/lib/hanami/cli/commands/new/schema.sql.erb +0 -0
  131. data/lib/hanami/cli/commands/new.rb +0 -578
  132. data/lib/hanami/cli/commands/project.rb +0 -421
  133. data/lib/hanami/cli/commands/routes.rb +0 -21
  134. data/lib/hanami/cli/commands/templates.rb +0 -31
  135. data/lib/hanami/cli/commands/version.rb +0 -19
  136. data/lib/hanami/common_logger.rb +0 -109
  137. data/lib/hanami/components/app/assets.rb +0 -59
  138. data/lib/hanami/components/app/controller.rb +0 -74
  139. data/lib/hanami/components/app/routes.rb +0 -59
  140. data/lib/hanami/components/app/view.rb +0 -44
  141. data/lib/hanami/components/component.rb +0 -182
  142. data/lib/hanami/components/components.rb +0 -479
  143. data/lib/hanami/components/routes_inspector.rb +0 -72
  144. data/lib/hanami/components.rb +0 -156
  145. data/lib/hanami/config/cookies.rb +0 -69
  146. data/lib/hanami/config/framework_configuration.rb +0 -43
  147. data/lib/hanami/config/load_paths.rb +0 -46
  148. data/lib/hanami/config/mapper.rb +0 -47
  149. data/lib/hanami/config/routes.rb +0 -20
  150. data/lib/hanami/config/security.rb +0 -110
  151. data/lib/hanami/config/sessions.rb +0 -119
  152. data/lib/hanami/configuration/app.rb +0 -21
  153. data/lib/hanami/early_hints.rb +0 -129
  154. data/lib/hanami/env.rb +0 -69
  155. data/lib/hanami/environment.rb +0 -541
  156. data/lib/hanami/environment_application_configurations.rb +0 -37
  157. data/lib/hanami/frameworks.rb +0 -22
  158. data/lib/hanami/hanamirc.rb +0 -169
  159. data/lib/hanami/mailer/glue.rb +0 -27
  160. data/lib/hanami/middleware_stack.rb +0 -172
  161. data/lib/hanami/rake_helper.rb +0 -78
  162. data/lib/hanami/rake_tasks.rb +0 -3
  163. data/lib/hanami/rendering_policy.rb +0 -94
  164. data/lib/hanami/routes.rb +0 -219
  165. data/lib/hanami/routing/default.rb +0 -32
  166. data/lib/hanami/static.rb +0 -63
  167. data/lib/hanami/templates/default.html.erb +0 -30
  168. data/lib/hanami/templates/welcome.html.erb +0 -52
  169. data/lib/hanami/views/default.rb +0 -37
  170. data/lib/hanami/views/default_template_finder.rb +0 -22
  171. data/lib/hanami/views/null_view.rb +0 -15
  172. data/lib/hanami/welcome.rb +0 -41
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/utils/string"
4
+ require "hanami/utils/class"
5
+
6
+ module Hanami
7
+ class Configuration
8
+ # Hanami configuration for HTTP sessions
9
+ #
10
+ # @since 2.0.0
11
+ class Sessions
12
+ NULL_SESSION_OPTION = :null
13
+ private_constant :NULL_SESSION_OPTION
14
+
15
+ def self.null
16
+ self.class.new(NULL_SESSION_OPTION)
17
+ end
18
+
19
+ attr_reader :storage, :options
20
+
21
+ def initialize(*args)
22
+ storage, options, = Array(args.dup).flatten
23
+
24
+ @storage = storage
25
+ @options = options || {}
26
+ end
27
+
28
+ def enabled?
29
+ storage != NULL_SESSION_OPTION
30
+ end
31
+
32
+ def middleware
33
+ [[storage_middleware, options]]
34
+ end
35
+
36
+ private
37
+
38
+ def storage_middleware
39
+ require_storage
40
+
41
+ name = Utils::String.classify(storage)
42
+ Utils::Class.load!(name, Rack::Session)
43
+ end
44
+
45
+ def require_storage
46
+ require "rack/session/#{storage}"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,215 +1,182 @@
1
- require 'concurrent'
2
- require 'hanami/application'
3
- require 'hanami/utils/class'
4
- require 'hanami/utils/string'
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+ require "concurrent/hash"
5
+ require "concurrent/array"
6
+ require "dry/configurable"
7
+ require "dry/inflector"
8
+ require "pathname"
9
+
10
+ require_relative "application/settings/dotenv_store"
11
+ require_relative "configuration/logger"
12
+ require_relative "configuration/middleware"
13
+ require_relative "configuration/router"
14
+ require_relative "configuration/sessions"
5
15
 
6
16
  module Hanami
7
- # @api private
17
+ # Hanami application configuration
18
+ #
19
+ # @since 2.0.0
20
+ #
21
+ # rubocop:disable Metrics/ClassLength
8
22
  class Configuration
9
- require "hanami/configuration/app"
10
- require "hanami/configuration/middleware"
23
+ include Dry::Configurable
24
+
25
+ DEFAULT_ENVIRONMENTS = Concurrent::Hash.new { |h, k| h[k] = Concurrent::Array.new }
26
+ private_constant :DEFAULT_ENVIRONMENTS
27
+
28
+ attr_reader :actions
29
+ attr_reader :middleware
30
+ attr_reader :router
31
+ attr_reader :views, :assets
32
+
33
+ attr_reader :environments
34
+ private :environments
35
+
36
+ def initialize(env:)
37
+ @environments = DEFAULT_ENVIRONMENTS.clone
38
+ config.env = env
39
+
40
+ # Some default setting values must be assigned at initialize-time to ensure they
41
+ # have appropriate values for the current application
42
+ self.root = Dir.pwd
43
+ self.settings_store = Application::Settings::DotenvStore.new.with_dotenv_loaded
44
+
45
+ @assets = begin
46
+ require_path = "hanami/assets/application_configuration"
47
+ require require_path
48
+ Hanami::Assets::ApplicationConfiguration.new
49
+ rescue LoadError => e
50
+ raise e unless e.path == require_path
51
+ require_relative "configuration/null_configuration"
52
+ NullConfiguration.new
53
+ end
54
+
55
+ # Config for actions (same for views, below) may not be available if the gem isn't
56
+ # loaded; fall back to a null config object if it's missing
57
+ @actions = begin
58
+ require_path = "hanami/action/application_configuration"
59
+ require require_path
60
+ Hanami::Action::ApplicationConfiguration.new(assets_server_url: assets.server_url)
61
+ rescue LoadError => e
62
+ raise e unless e.path == require_path
63
+ require_relative "configuration/null_configuration"
64
+ NullConfiguration.new
65
+ end
11
66
 
12
- # @api private
13
- def initialize(&blk)
14
- @settings = Concurrent::Map.new
15
- instance_eval(&blk)
67
+ @middleware = Middleware.new
68
+
69
+ @router = Router.new(self)
70
+
71
+ @views = begin
72
+ require_path = "hanami/view/application_configuration"
73
+ require require_path
74
+ Hanami::View::ApplicationConfiguration.new
75
+ rescue LoadError => e
76
+ raise e unless e.path == require_path
77
+ require_relative "configuration/null_configuration"
78
+ NullConfiguration.new
79
+ end
80
+
81
+ yield self if block_given?
16
82
  end
17
83
 
18
- # Mount a Hanami::Application or a Rack app
19
- #
20
- # @param app [#call] an application compatible with Rack SPEC
21
- # @param options [Hash] a set of options
22
- # @option :at [String] options the mount point
23
- # @option :host [String] options the mount point
24
- #
25
- # @since 0.9.0
26
- #
27
- # @example
28
- # # config/environment.rb
29
- # # ...
30
- # Hanami.configure do
31
- # mount Beta::Application, at: '/', host: 'beta.bookshelf.com'
32
- # mount Admin::Application, at: '/api'
33
- # mount Web::Application, at: '/'
34
- #
35
- # # ...
36
- # end
37
- def mount(app, options)
38
- mounted[app] = App.new(app, options)
84
+ def environment(env_name, &block)
85
+ environments[env_name] << block
86
+ apply_env_config
87
+
88
+ self
39
89
  end
40
90
 
41
- # Configure database
42
- #
43
- # @param blk [Proc] the database configuration
44
- #
45
- # @see Hanami::Model.configure
46
- #
47
- # @example
48
- # # config/environment.rb
49
- # # ...
50
- # Hanami.configure do
51
- # model do
52
- # adapter :sql, ENV['DATABASE_URL']
53
- #
54
- # migrations 'db/migrations'
55
- # schema 'db/schema.sql'
56
- # end
57
- #
58
- # # ...
59
- # end
60
- def model(&blk)
61
- if block_given?
62
- settings.put_if_absent(:model, blk)
63
- else
64
- settings.fetch(:model)
65
- end
91
+ def finalize!
92
+ apply_env_config
93
+
94
+ # Finalize nested configurations
95
+ assets.finalize!
96
+ actions.finalize!
97
+ views.finalize!
98
+ logger.finalize!
99
+ router.finalize!
100
+
101
+ super
66
102
  end
67
103
 
68
- # Configure mailer
69
- #
70
- # @param blk [Proc] the mailer configuration
71
- #
72
- # @see Hanami::Mailer.configure
73
- #
74
- # @example
75
- # # config/environment.rb
76
- # # ...
77
- # Hanami.configure do
78
- # mailer do
79
- # root 'lib/bookshelf/mailers'
80
- #
81
- # # See https://guides.hanamirb.org/mailers/delivery
82
- # delivery :test
83
- # end
84
- #
85
- # # ...
86
- # end
87
- def mailer(&blk)
88
- mailer_settings.push(blk) if block_given?
104
+ setting :env
105
+
106
+ def env=(new_env)
107
+ config.env = env
108
+ apply_env_config(new_env)
89
109
  end
90
110
 
91
- # @since next
92
- # @api private
93
- def mailer_settings
94
- settings.fetch_or_store(:mailers, [])
111
+ setting :root, constructor: -> path { Pathname(path) }
112
+
113
+ setting :inflector, default: Dry::Inflector.new, cloneable: true
114
+
115
+ def inflections(&block)
116
+ self.inflector = Dry::Inflector.new(&block)
95
117
  end
96
118
 
97
- # @since 0.9.0
98
- # @api private
99
- def mounted
100
- settings.fetch_or_store(:mounted, {})
119
+ setting :logger, default: Configuration::Logger.new, cloneable: true
120
+
121
+ def logger=(logger_instance)
122
+ @logger_instance = logger_instance
101
123
  end
102
124
 
103
- # @since 1.2.0
104
- #
105
- # @example
106
- # # config/environment.rb
107
- # # ...
108
- # Hanami.configure do
109
- # middleware.use MyRackMiddleware
110
- # end
111
- def middleware
112
- settings.fetch_or_store(:middleware, Configuration::Middleware.new)
125
+ def logger_instance
126
+ @logger_instance || logger.logger_class.new(**logger.options)
113
127
  end
114
128
 
115
- # Setup Early Hints feature
116
- #
117
- # @since 1.2.0
118
- #
119
- # @example Enable for all the environments
120
- # # config/environment.rb
121
- # Hanami.configure do
122
- # early_hints true
123
- # end
124
- #
125
- # @example Enable only for production
126
- # # config/environment.rb
127
- # Hanami.configure do
128
- # environment :production do
129
- # early_hints true
130
- # end
131
- # end
132
- def early_hints(value = nil)
133
- if value.nil?
134
- settings.fetch(:early_hints, false)
135
- else
136
- settings[:early_hints] = value
137
- end
129
+ setting :settings_path, default: File.join("config", "settings")
130
+
131
+ setting :settings_class_name, default: "Settings"
132
+
133
+ setting :settings_store, default: Application::Settings::DotenvStore
134
+
135
+ setting :slices_dir, default: "slices"
136
+
137
+ setting :slices_namespace, default: Object
138
+
139
+ # TODO: convert into a dedicated object with explicit behaviour around blocks per
140
+ # slice, etc.
141
+ setting :slices, default: {}, constructor: :dup.to_proc
142
+
143
+ # TODO: turn this into a richer "source dirs" setting that can support enabling
144
+ # of container component loading as an opt in behvior
145
+ setting :component_dir_paths, default: %w[actions repositories views]
146
+
147
+ def slice(slice_name, &block)
148
+ slices[slice_name] = block
138
149
  end
139
150
 
140
- # @since 0.9.0
141
- # @api private
142
- def apps
143
- mounted.each_pair do |klass, app|
144
- yield(app) if klass <= Hanami::Application
151
+ setting :base_url, default: "http://0.0.0.0:2300", constructor: -> url { URI(url) }
152
+
153
+ def for_each_middleware(&blk)
154
+ stack = middleware.stack.dup
155
+ stack += sessions.middleware if sessions.enabled?
156
+
157
+ stack.each(&blk)
158
+ end
159
+
160
+ setting :sessions, default: :null, constructor: -> *args { Sessions.new(*args) }
161
+
162
+ private
163
+
164
+ def apply_env_config(env = self.env)
165
+ environments[env].each do |block|
166
+ instance_eval(&block)
145
167
  end
146
168
  end
147
169
 
148
- # Configure logger
149
- #
150
- # @since 1.0.0
151
- #
152
- # @param options [Array] a set of options
153
- #
154
- # @see Hanami.logger
155
- # @see Hanami::Logger
156
- #
157
- # @see https://guides.hanamirb.org/projects/logging
158
- #
159
- # @example Basic Usage
160
- # # config/environment.rb
161
- # # ...
162
- # Hanami.configure do
163
- # # ...
164
- # environment :development do
165
- # logger level: :debug
166
- # end
167
- # end
168
- #
169
- # @example Daily Rotation
170
- # # config/environment.rb
171
- # # ...
172
- # Hanami.configure do
173
- # # ...
174
- # environment :development do
175
- # logger 'daily', level: :debug
176
- # end
177
- # end
178
- def logger(*options)
179
- if options.empty?
180
- settings.fetch(:logger, nil)
170
+ def method_missing(name, *args, &block)
171
+ if config.respond_to?(name)
172
+ config.public_send(name, *args, &block)
181
173
  else
182
- settings[:logger] = options
174
+ super
183
175
  end
184
176
  end
185
177
 
186
- # Configure settings for the current environment
187
- # @since 1.0.0
188
- #
189
- # @param name [Symbol] the name of the Hanami environment
190
- #
191
- # @see Hanami.env
192
- #
193
- # @example Configure Logging for Different Environments
194
- # # config/environment.rb
195
- # # ...
196
- # Hanami.configure do
197
- # # ...
198
- # environment :development do
199
- # logger level: :debug
200
- # end
201
- #
202
- # environment :production do
203
- # logger level: :info, formatter: :json
204
- # end
205
- # end
206
- def environment(name)
207
- yield if ENV['HANAMI_ENV'] == name.to_s
178
+ def respond_to_missing?(name, _incude_all = false)
179
+ config.respond_to?(name) || super
208
180
  end
209
-
210
- private
211
-
212
- # @api private
213
- attr_reader :settings
214
181
  end
215
182
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setup"
4
+
5
+ Hanami.init
data/lib/hanami/server.rb CHANGED
@@ -1,4 +1,7 @@
1
- require 'rack'
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami"
4
+ require "rack"
2
5
 
3
6
  module Hanami
4
7
  # Rack compatible server.
@@ -13,81 +16,14 @@ module Hanami
13
16
  # @since 0.8.0
14
17
  # @api private
15
18
  class Server < ::Rack::Server
16
- # @api private
17
- attr_reader :options
18
-
19
- # @since 0.8.0
20
- # @api private
21
- #
22
- # @see Hanami::Environment#initialize
23
- def initialize
24
- @options = _extract_options
25
- setup
26
- end
27
-
28
19
  # Primarily this removes the ::Rack::Chunked middleware
29
20
  # which is the cause of Safari content-length bugs.
30
21
  #
31
22
  # @since 0.8.0
32
23
  def middleware
33
- mw = Hash.new { |e, m| e[m] = [] }
24
+ mw = ::Hash.new { |e, m| e[m] = [] }
34
25
  mw["development"].concat([::Rack::ShowExceptions, ::Rack::Lint])
35
- require 'hanami/assets/static'
36
- mw["development"].push(::Hanami::Assets::Static)
37
26
  mw
38
27
  end
39
-
40
- # @api private
41
- def start
42
- preload
43
- super
44
- end
45
-
46
- private
47
-
48
- # @api private
49
- def setup
50
- return unless code_reloading?
51
- @app = Shotgun::Loader.new(rackup)
52
- end
53
-
54
- # @api private
55
- def environment
56
- Components['environment']
57
- end
58
-
59
- # @since 0.8.0
60
- # @api private
61
- def code_reloading?
62
- Hanami.code_reloading?
63
- end
64
-
65
- # @api private
66
- def rackup
67
- environment.rackup.to_s
68
- end
69
-
70
- # @api private
71
- def preload
72
- if code_reloading?
73
- Shotgun.enable_copy_on_write
74
- Shotgun.preload
75
- else
76
- Hanami.boot
77
- end
78
- end
79
-
80
- # Options for Rack::Server superclass
81
- #
82
- # @since 0.8.0
83
- # @api private
84
- def _extract_options
85
- environment.to_options.merge(
86
- config: rackup,
87
- Host: environment.host,
88
- Port: environment.port,
89
- AccessLog: []
90
- )
91
- end
92
28
  end
93
29
  end
data/lib/hanami/setup.rb CHANGED
@@ -1,3 +1,9 @@
1
- require 'hanami'
1
+ # frozen_string_literal: true
2
2
 
3
- ::Bundler.require(*Hanami::Environment.new.bundler_groups)
3
+ require "bundler/setup"
4
+ require "hanami"
5
+
6
+ begin
7
+ require File.join(Dir.pwd, "config/application")
8
+ rescue LoadError # rubocop:disable Lint/SuppressedException
9
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/system/container"
4
+ require "dry/system/loader/autoloading"
5
+ require "pathname"
6
+
7
+ module Hanami
8
+ # Distinct area of concern within an Hanami application
9
+ #
10
+ # @since 2.0.0
11
+ class Slice
12
+ attr_reader :application, :name, :namespace, :root
13
+
14
+ def initialize(application, name:, namespace: nil, root: nil, container: nil)
15
+ @application = application
16
+ @name = name.to_sym
17
+ @namespace = namespace
18
+ @root = root ? Pathname(root) : root
19
+ @container = container || define_container
20
+ end
21
+
22
+ def inflector
23
+ application.inflector
24
+ end
25
+
26
+ def namespace_path
27
+ @namespace_path ||= inflector.underscore(namespace.to_s)
28
+ end
29
+
30
+ def init
31
+ container.import application: application.container
32
+
33
+ slice_block = application.configuration.slices[name]
34
+ instance_eval(&slice_block) if slice_block
35
+ end
36
+
37
+ def boot
38
+ container.finalize! do
39
+ container.config.env = application.container.config.env
40
+ end
41
+
42
+ @booted = true
43
+ self
44
+ end
45
+
46
+ # rubocop:disable Style/DoubleNegation
47
+ def booted?
48
+ !!@booted
49
+ end
50
+ # rubocop:enable Style/DoubleNegation
51
+
52
+ def container
53
+ @container ||= define_container
54
+ end
55
+
56
+ def import(*slice_names)
57
+ raise "Cannot import after booting" if booted?
58
+
59
+ slice_names.each do |slice_name|
60
+ container.import slice_name.to_sym => application.slices.fetch(slice_name.to_sym).container
61
+ end
62
+ end
63
+
64
+ def register(*args, &block)
65
+ container.register(*args, &block)
66
+ end
67
+
68
+ def register_bootable(*args, &block)
69
+ container.boot(*args, &block)
70
+ end
71
+
72
+ def init_bootable(*args)
73
+ container.init(*args)
74
+ end
75
+
76
+ def start_bootable(*args)
77
+ container.start(*args)
78
+ end
79
+
80
+ def key?(*args)
81
+ container.key?(*args)
82
+ end
83
+
84
+ def keys
85
+ container.keys
86
+ end
87
+
88
+ def [](*args)
89
+ container[*args]
90
+ end
91
+
92
+ def resolve(*args)
93
+ container.resolve(*args)
94
+ end
95
+
96
+ private
97
+
98
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
99
+ def define_container
100
+ container = Class.new(Dry::System::Container)
101
+ container.use :env
102
+
103
+ container.configure do |config|
104
+ config.name = name
105
+ config.inflector = application.configuration.inflector
106
+
107
+ config.component_dirs.loader = Dry::System::Loader::Autoloading
108
+ config.component_dirs.add_to_load_path = false
109
+
110
+ if root&.directory?
111
+ config.root = root
112
+ config.bootable_dirs = ["config/boot"]
113
+
114
+ # Add the "lib" component dir; all slices will load components from lib
115
+ if root.join("lib").directory?
116
+ config.component_dirs.add("lib") do |component_dir|
117
+ # Expect component files in the root of the lib
118
+ # component dir to define classes inside the slice's namespace.
119
+ #
120
+ # e.g. "lib/foo.rb" should define SliceNamespace::Foo, and will be
121
+ # registered as "foo"
122
+ component_dir.namespaces.root(key: nil, const: namespace_path)
123
+
124
+ application.autoloader.push_dir(root.join("lib"), namespace: namespace)
125
+ end
126
+ end
127
+
128
+ # Add component dirs for each configured component path
129
+ application.configuration.component_dir_paths.each do |slice_dir|
130
+ next unless root.join(slice_dir).directory?
131
+
132
+ config.component_dirs.add(slice_dir) do |component_dir|
133
+ # Expect component files in the root of these component dirs to define
134
+ # classes inside a namespace matching the dir.
135
+ #
136
+ # e.g. "actions/foo.rb" should define SliceNamespace::Actions::Foo, and
137
+ # will be registered as "actions.foo"
138
+
139
+ dir_namespace_path = File.join(namespace_path, slice_dir)
140
+
141
+ autoloader_namespace = begin
142
+ inflector.constantize(inflector.camelize(dir_namespace_path))
143
+ rescue NameError
144
+ namespace.const_set(inflector.camelize(slice_dir), Module.new)
145
+ end
146
+
147
+ component_dir.namespaces.root(const: dir_namespace_path, key: slice_dir)
148
+
149
+ application.autoloader.push_dir(
150
+ container.root.join(slice_dir),
151
+ namespace: autoloader_namespace
152
+ )
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ if namespace
159
+ namespace.const_set :Container, container
160
+ namespace.const_set :Deps, container.injector
161
+ end
162
+
163
+ container
164
+ end
165
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
166
+ end
167
+ end