hanami 2.0.0.alpha8 → 2.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +442 -241
  3. data/FEATURES.md +30 -9
  4. data/README.md +1 -3
  5. data/hanami.gemspec +21 -11
  6. data/lib/hanami/app.rb +141 -0
  7. data/lib/hanami/assets/application_configuration.rb +10 -4
  8. data/lib/hanami/configuration/actions/content_security_policy.rb +5 -5
  9. data/lib/hanami/configuration/actions/cookies.rb +2 -2
  10. data/lib/hanami/configuration/actions.rb +10 -4
  11. data/lib/hanami/configuration/logger.rb +4 -4
  12. data/lib/hanami/configuration/router.rb +2 -6
  13. data/lib/hanami/configuration/sessions.rb +1 -1
  14. data/lib/hanami/configuration/views.rb +9 -4
  15. data/lib/hanami/configuration.rb +118 -46
  16. data/lib/hanami/constants.rb +24 -2
  17. data/lib/hanami/errors.rb +1 -1
  18. data/lib/hanami/{application → extensions}/action/slice_configured_action.rb +9 -9
  19. data/lib/hanami/extensions/action.rb +79 -0
  20. data/lib/hanami/extensions/view/context.rb +106 -0
  21. data/lib/hanami/{application → extensions}/view/slice_configured_context.rb +10 -10
  22. data/lib/hanami/{application → extensions}/view/slice_configured_view.rb +12 -6
  23. data/lib/hanami/extensions/view.rb +33 -0
  24. data/lib/hanami/extensions.rb +10 -0
  25. data/lib/hanami/providers/inflector.rb +13 -0
  26. data/lib/hanami/providers/logger.rb +13 -0
  27. data/lib/hanami/providers/rack.rb +27 -0
  28. data/lib/hanami/providers/routes.rb +33 -0
  29. data/lib/hanami/providers/settings.rb +23 -0
  30. data/lib/hanami/rake_tasks.rb +61 -0
  31. data/lib/hanami/routes.rb +51 -0
  32. data/lib/hanami/server.rb +1 -1
  33. data/lib/hanami/settings/dotenv_store.rb +58 -0
  34. data/lib/hanami/settings.rb +90 -0
  35. data/lib/hanami/setup.rb +4 -2
  36. data/lib/hanami/{application → slice}/router.rb +18 -13
  37. data/lib/hanami/slice/routes_helper.rb +37 -0
  38. data/lib/hanami/{application → slice}/routing/middleware/stack.rb +43 -5
  39. data/lib/hanami/slice/routing/resolver.rb +97 -0
  40. data/lib/hanami/{application → slice}/view_name_inferrer.rb +3 -3
  41. data/lib/hanami/slice.rb +246 -73
  42. data/lib/hanami/slice_configurable.rb +4 -17
  43. data/lib/hanami/slice_name.rb +6 -6
  44. data/lib/hanami/slice_registrar.rb +119 -0
  45. data/lib/hanami/version.rb +1 -1
  46. data/lib/hanami/web/rack_logger.rb +1 -1
  47. data/lib/hanami.rb +34 -26
  48. data/spec/integration/application_middleware_stack_spec.rb +84 -0
  49. data/spec/integration/assets/cdn_spec.rb +48 -0
  50. data/spec/integration/assets/fingerprint_spec.rb +42 -0
  51. data/spec/integration/assets/helpers_spec.rb +50 -0
  52. data/spec/integration/assets/serve_spec.rb +70 -0
  53. data/spec/integration/assets/subresource_integrity_spec.rb +54 -0
  54. data/spec/integration/body_parsers_spec.rb +50 -0
  55. data/spec/integration/cli/assets/precompile_spec.rb +147 -0
  56. data/spec/integration/cli/assets_spec.rb +14 -0
  57. data/spec/integration/cli/console_spec.rb +105 -0
  58. data/spec/integration/cli/db/apply_spec.rb +74 -0
  59. data/spec/integration/cli/db/console_spec.rb +40 -0
  60. data/spec/integration/cli/db/create_spec.rb +50 -0
  61. data/spec/integration/cli/db/drop_spec.rb +54 -0
  62. data/spec/integration/cli/db/migrate_spec.rb +108 -0
  63. data/spec/integration/cli/db/prepare_spec.rb +36 -0
  64. data/spec/integration/cli/db/rollback_spec.rb +96 -0
  65. data/spec/integration/cli/db/version_spec.rb +38 -0
  66. data/spec/integration/cli/db_spec.rb +21 -0
  67. data/spec/integration/cli/destroy/action_spec.rb +143 -0
  68. data/spec/integration/cli/destroy/app_spec.rb +118 -0
  69. data/spec/integration/cli/destroy/mailer_spec.rb +74 -0
  70. data/spec/integration/cli/destroy/migration_spec.rb +70 -0
  71. data/spec/integration/cli/destroy/model_spec.rb +113 -0
  72. data/spec/integration/cli/destroy_spec.rb +18 -0
  73. data/spec/integration/cli/generate/action_spec.rb +469 -0
  74. data/spec/integration/cli/generate/app_spec.rb +215 -0
  75. data/spec/integration/cli/generate/mailer_spec.rb +189 -0
  76. data/spec/integration/cli/generate/migration_spec.rb +72 -0
  77. data/spec/integration/cli/generate/model_spec.rb +290 -0
  78. data/spec/integration/cli/generate/secret_spec.rb +56 -0
  79. data/spec/integration/cli/generate_spec.rb +19 -0
  80. data/spec/integration/cli/new/database_spec.rb +235 -0
  81. data/spec/integration/cli/new/hanami_head_spec.rb +27 -0
  82. data/spec/integration/cli/new/template_spec.rb +118 -0
  83. data/spec/integration/cli/new/test_spec.rb +274 -0
  84. data/spec/integration/cli/new_spec.rb +970 -0
  85. data/spec/integration/cli/plugins_spec.rb +39 -0
  86. data/spec/integration/cli/routes_spec.rb +49 -0
  87. data/spec/integration/cli/server_spec.rb +626 -0
  88. data/spec/integration/cli/version_spec.rb +85 -0
  89. data/spec/integration/early_hints_spec.rb +35 -0
  90. data/spec/integration/handle_exceptions_spec.rb +244 -0
  91. data/spec/integration/head_spec.rb +89 -0
  92. data/spec/integration/http_headers_spec.rb +29 -0
  93. data/spec/integration/mailer_spec.rb +32 -0
  94. data/spec/integration/middleware_spec.rb +81 -0
  95. data/spec/integration/mount_applications_spec.rb +88 -0
  96. data/spec/integration/project_initializers_spec.rb +40 -0
  97. data/spec/integration/rackup_spec.rb +35 -0
  98. data/spec/integration/rake/with_minitest_spec.rb +67 -0
  99. data/spec/integration/rake/with_rspec_spec.rb +69 -0
  100. data/spec/integration/routing_helpers_spec.rb +61 -0
  101. data/spec/integration/security/content_security_policy_spec.rb +46 -0
  102. data/spec/integration/security/csrf_protection_spec.rb +42 -0
  103. data/spec/integration/security/force_ssl_spec.rb +29 -0
  104. data/spec/integration/security/x_content_type_options_spec.rb +46 -0
  105. data/spec/integration/security/x_frame_options_spec.rb +46 -0
  106. data/spec/integration/security/x_xss_protection_spec.rb +46 -0
  107. data/spec/integration/send_file_spec.rb +51 -0
  108. data/spec/integration/sessions_spec.rb +247 -0
  109. data/spec/integration/static_middleware_spec.rb +21 -0
  110. data/spec/integration/streaming_spec.rb +41 -0
  111. data/spec/integration/unsafe_send_file_spec.rb +52 -0
  112. data/spec/isolation/hanami/application/already_configured_spec.rb +19 -0
  113. data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +10 -0
  114. data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +14 -0
  115. data/spec/isolation/hanami/application/not_configured_spec.rb +9 -0
  116. data/spec/isolation/hanami/application/routes/configured_spec.rb +44 -0
  117. data/spec/isolation/hanami/application/routes/not_configured_spec.rb +16 -0
  118. data/spec/isolation/hanami/boot/success_spec.rb +50 -0
  119. data/spec/new_integration/action/configuration_spec.rb +26 -0
  120. data/spec/new_integration/action/cookies_spec.rb +58 -0
  121. data/spec/new_integration/action/csrf_protection_spec.rb +54 -0
  122. data/spec/new_integration/action/routes_spec.rb +73 -0
  123. data/spec/new_integration/action/sessions_spec.rb +50 -0
  124. data/spec/new_integration/action/view_integration_spec.rb +165 -0
  125. data/spec/new_integration/action/view_rendering/automatic_rendering_spec.rb +247 -0
  126. data/spec/new_integration/action/view_rendering/paired_view_inference_spec.rb +115 -0
  127. data/spec/new_integration/action/view_rendering_spec.rb +107 -0
  128. data/spec/new_integration/code_loading/loading_from_app_spec.rb +152 -0
  129. data/spec/new_integration/code_loading/loading_from_slice_spec.rb +165 -0
  130. data/spec/new_integration/container/application_routes_helper_spec.rb +48 -0
  131. data/spec/new_integration/container/auto_injection_spec.rb +53 -0
  132. data/spec/new_integration/container/auto_registration_spec.rb +86 -0
  133. data/spec/new_integration/container/autoloader_spec.rb +80 -0
  134. data/spec/new_integration/container/imports_spec.rb +253 -0
  135. data/spec/new_integration/container/prepare_container_spec.rb +123 -0
  136. data/spec/new_integration/container/shutdown_spec.rb +91 -0
  137. data/spec/new_integration/container/standard_bootable_components_spec.rb +124 -0
  138. data/spec/new_integration/rack_app/middleware_spec.rb +215 -0
  139. data/spec/new_integration/rack_app/non_booted_rack_app_spec.rb +105 -0
  140. data/spec/new_integration/rack_app/rack_app_spec.rb +524 -0
  141. data/spec/new_integration/settings_spec.rb +115 -0
  142. data/spec/new_integration/slices/external_slice_spec.rb +92 -0
  143. data/spec/new_integration/slices/slice_configuration_spec.rb +40 -0
  144. data/spec/new_integration/slices/slice_routing_spec.rb +226 -0
  145. data/spec/new_integration/slices/slice_settings_spec.rb +141 -0
  146. data/spec/new_integration/slices_spec.rb +101 -0
  147. data/spec/new_integration/view/configuration_spec.rb +49 -0
  148. data/spec/new_integration/view/context/assets_spec.rb +67 -0
  149. data/spec/new_integration/view/context/inflector_spec.rb +48 -0
  150. data/spec/new_integration/view/context/request_spec.rb +61 -0
  151. data/spec/new_integration/view/context/routes_spec.rb +86 -0
  152. data/spec/new_integration/view/context/settings_spec.rb +50 -0
  153. data/spec/new_integration/view/inflector_spec.rb +57 -0
  154. data/spec/new_integration/view/part_namespace_spec.rb +96 -0
  155. data/spec/new_integration/view/path_spec.rb +56 -0
  156. data/spec/new_integration/view/template_spec.rb +68 -0
  157. data/spec/new_integration/view/views_spec.rb +103 -0
  158. data/spec/spec_helper.rb +16 -0
  159. data/spec/support/app_integration.rb +91 -0
  160. data/spec/support/coverage.rb +1 -0
  161. data/spec/support/fixtures/hanami-plugin/Gemfile +8 -0
  162. data/spec/support/fixtures/hanami-plugin/README.md +35 -0
  163. data/spec/support/fixtures/hanami-plugin/Rakefile +4 -0
  164. data/spec/support/fixtures/hanami-plugin/bin/console +15 -0
  165. data/spec/support/fixtures/hanami-plugin/bin/setup +8 -0
  166. data/spec/support/fixtures/hanami-plugin/hanami-plugin.gemspec +28 -0
  167. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/cli.rb +19 -0
  168. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/version.rb +7 -0
  169. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin.rb +8 -0
  170. data/spec/support/rspec.rb +27 -0
  171. data/spec/support/shared_examples/cli/generate/app.rb +494 -0
  172. data/spec/support/shared_examples/cli/generate/migration.rb +32 -0
  173. data/spec/support/shared_examples/cli/generate/model.rb +81 -0
  174. data/spec/support/shared_examples/cli/new.rb +97 -0
  175. data/spec/unit/hanami/configuration/actions/content_security_policy_spec.rb +102 -0
  176. data/spec/unit/hanami/configuration/actions/cookies_spec.rb +46 -0
  177. data/spec/unit/hanami/configuration/actions/csrf_protection_spec.rb +57 -0
  178. data/spec/unit/hanami/configuration/actions/default_values_spec.rb +52 -0
  179. data/spec/unit/hanami/configuration/actions/sessions_spec.rb +50 -0
  180. data/spec/unit/hanami/configuration/actions_spec.rb +78 -0
  181. data/spec/unit/hanami/configuration/base_url_spec.rb +25 -0
  182. data/spec/unit/hanami/configuration/inflector_spec.rb +35 -0
  183. data/spec/unit/hanami/configuration/logger_spec.rb +203 -0
  184. data/spec/unit/hanami/configuration/views_spec.rb +120 -0
  185. data/spec/unit/hanami/configuration_spec.rb +43 -0
  186. data/spec/unit/hanami/env_spec.rb +54 -0
  187. data/spec/unit/hanami/routes_spec.rb +25 -0
  188. data/spec/unit/hanami/settings/dotenv_store_spec.rb +119 -0
  189. data/spec/unit/hanami/settings_spec.rb +56 -0
  190. data/spec/unit/hanami/slice_configurable_spec.rb +104 -0
  191. data/spec/unit/hanami/slice_name_spec.rb +47 -0
  192. data/spec/unit/hanami/slice_spec.rb +17 -0
  193. data/spec/unit/hanami/version_spec.rb +7 -0
  194. data/spec/unit/hanami/web/rack_logger_spec.rb +78 -0
  195. metadata +353 -57
  196. data/lib/hanami/application/action.rb +0 -72
  197. data/lib/hanami/application/container/providers/inflector.rb +0 -7
  198. data/lib/hanami/application/container/providers/logger.rb +0 -7
  199. data/lib/hanami/application/container/providers/rack_logger.rb +0 -15
  200. data/lib/hanami/application/container/providers/rack_monitor.rb +0 -12
  201. data/lib/hanami/application/container/providers/routes_helper.rb +0 -9
  202. data/lib/hanami/application/container/providers/settings.rb +0 -7
  203. data/lib/hanami/application/routes.rb +0 -55
  204. data/lib/hanami/application/routes_helper.rb +0 -34
  205. data/lib/hanami/application/routing/resolver/node.rb +0 -50
  206. data/lib/hanami/application/routing/resolver/trie.rb +0 -59
  207. data/lib/hanami/application/routing/resolver.rb +0 -87
  208. data/lib/hanami/application/routing/router.rb +0 -36
  209. data/lib/hanami/application/settings/dotenv_store.rb +0 -60
  210. data/lib/hanami/application/settings.rb +0 -93
  211. data/lib/hanami/application/slice_registrar.rb +0 -106
  212. data/lib/hanami/application/view/context.rb +0 -95
  213. data/lib/hanami/application/view.rb +0 -24
  214. data/lib/hanami/application.rb +0 -273
  215. data/lib/hanami/cli/application/cli.rb +0 -40
  216. data/lib/hanami/cli/application/command.rb +0 -47
  217. data/lib/hanami/cli/application/commands/console.rb +0 -81
  218. data/lib/hanami/cli/application/commands.rb +0 -16
  219. data/lib/hanami/cli/base_command.rb +0 -48
  220. data/lib/hanami/cli/commands/command.rb +0 -171
  221. data/lib/hanami/cli/commands/server.rb +0 -88
  222. data/lib/hanami/cli/commands.rb +0 -65
  223. data/lib/hanami/configuration/middleware.rb +0 -20
  224. data/lib/hanami/configuration/source_dirs.rb +0 -42
@@ -1,273 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dry/system/container"
4
- require "hanami/configuration"
5
- require "pathname"
6
- require "rack"
7
- require "zeitwerk"
8
- require_relative "constants"
9
- require_relative "slice"
10
- require_relative "slice_name"
11
- require_relative "application/slice_registrar"
12
-
13
- module Hanami
14
- # Hanami application class
15
- #
16
- # @since 2.0.0
17
- class Application
18
- @_mutex = Mutex.new
19
-
20
- class << self
21
- def inherited(subclass)
22
- super
23
-
24
- @_mutex.synchronize do
25
- subclass.class_eval do
26
- @_mutex = Mutex.new
27
- @application_name = SliceName.new(subclass, inflector: -> { subclass.inflector })
28
- @configuration = Hanami::Configuration.new(application_name: @application_name, env: Hanami.env)
29
- @autoloader = Zeitwerk::Loader.new
30
- @container = Class.new(Dry::System::Container)
31
-
32
- @prepared = @booted = false
33
-
34
- extend ClassMethods
35
- end
36
-
37
- subclass.send :prepare_base_load_path
38
-
39
- Hanami.application = subclass
40
- end
41
- end
42
- end
43
-
44
- # Application class interface
45
- #
46
- # rubocop:disable Metrics/ModuleLength
47
- module ClassMethods
48
- attr_reader :application_name, :configuration, :autoloader, :container
49
-
50
- alias_method :slice_name, :application_name
51
-
52
- alias_method :config, :configuration
53
-
54
- def application
55
- self
56
- end
57
-
58
- def prepare(provider_name = nil)
59
- container.prepare(provider_name) and return self if provider_name
60
-
61
- return self if prepared?
62
-
63
- configuration.finalize!
64
-
65
- prepare_all
66
-
67
- @prepared = true
68
- self
69
- end
70
-
71
- def boot(&block)
72
- return self if booted?
73
-
74
- prepare
75
-
76
- container.finalize!(&block)
77
-
78
- slices.each(&:boot)
79
-
80
- @booted = true
81
- self
82
- end
83
-
84
- def shutdown
85
- slices.each(&:shutdown)
86
- container.shutdown!
87
- self
88
- end
89
-
90
- def prepared?
91
- !!@prepared
92
- end
93
-
94
- def booted?
95
- !!@booted
96
- end
97
-
98
- def router
99
- raise "Application not yet prepared" unless prepared?
100
-
101
- @_mutex.synchronize do
102
- @_router ||= load_router
103
- end
104
- end
105
-
106
- def rack_app
107
- @rack_app ||= router.to_rack_app
108
- end
109
-
110
- def slices
111
- @slices ||= SliceRegistrar.new(self)
112
- end
113
-
114
- def register_slice(...)
115
- slices.register(...)
116
- end
117
-
118
- def register(...)
119
- container.register(...)
120
- end
121
-
122
- def register_provider(...)
123
- container.register_provider(...)
124
- end
125
-
126
- def start(...)
127
- container.start(...)
128
- end
129
-
130
- def key?(...)
131
- container.key?(...)
132
- end
133
-
134
- def keys
135
- container.keys
136
- end
137
-
138
- def [](...)
139
- container.[](...)
140
- end
141
-
142
- def resolve(...)
143
- container.resolve(...)
144
- end
145
-
146
- def settings
147
- @_settings ||= load_settings
148
- end
149
-
150
- def namespace
151
- application_name.namespace
152
- end
153
-
154
- def root
155
- configuration.root
156
- end
157
-
158
- def inflector
159
- configuration.inflector
160
- end
161
-
162
- private
163
-
164
- def prepare_base_load_path
165
- base_path = File.join(root, "lib")
166
- $LOAD_PATH.unshift base_path unless $LOAD_PATH.include?(base_path)
167
- end
168
-
169
- def prepare_all
170
- load_settings
171
- prepare_container_plugins
172
- prepare_container_base_config
173
- prepare_container_consts
174
- container.configured!
175
- prepare_slices
176
- # For the application, the autoloader must be prepared after the slices, since
177
- # they'll be configuring the autoloader with their own dirs
178
- prepare_autoloader
179
- end
180
-
181
- def prepare_container_plugins
182
- container.use(:env, inferrer: -> { Hanami.env })
183
- container.use(:zeitwerk, loader: autoloader, run_setup: false, eager_load: false)
184
- container.use(:notifications)
185
- end
186
-
187
- def prepare_container_base_config
188
- container.config.root = configuration.root
189
- container.config.inflector = configuration.inflector
190
-
191
- container.config.provider_dirs = [
192
- "config/providers",
193
- Pathname(__dir__).join("application/container/providers").realpath,
194
- ]
195
- end
196
-
197
- def prepare_autoload_paths
198
- # Autoload classes defined in lib/[app_namespace]/
199
- if root.join("lib", application_name.name).directory?
200
- autoloader.push_dir(root.join("lib", application_name.name), namespace: namespace)
201
- end
202
- end
203
-
204
- def prepare_container_consts
205
- namespace.const_set :Container, container
206
- namespace.const_set :Deps, container.injector
207
- end
208
-
209
- def prepare_slices
210
- slices.load_slices.each(&:prepare)
211
- slices.freeze
212
- end
213
-
214
- def prepare_autoloader
215
- # Autoload classes defined in lib/[app_namespace]/
216
- if root.join("lib", application_name.name).directory?
217
- autoloader.push_dir(root.join("lib", application_name.name), namespace: namespace)
218
- end
219
-
220
- autoloader.setup
221
- end
222
-
223
- def load_settings
224
- require_relative "application/settings"
225
-
226
- prepare_base_load_path
227
- require File.join(configuration.root, configuration.settings_path)
228
- settings_class = autodiscover_application_constant(configuration.settings_class_name)
229
- settings_class.new(configuration.settings_store)
230
- rescue LoadError
231
- Settings.new
232
- end
233
-
234
- def autodiscover_application_constant(constants)
235
- inflector.constantize([application_name.namespace_name, *constants].join(MODULE_DELIMITER))
236
- end
237
-
238
- def load_router
239
- require_relative "application/router"
240
-
241
- Router.new(
242
- routes: load_routes,
243
- resolver: router_resolver,
244
- **configuration.router.options,
245
- ) do
246
- use Hanami.application[:rack_monitor]
247
-
248
- Hanami.application.config.for_each_middleware do |m, *args, &block|
249
- use(m, *args, &block)
250
- end
251
- end
252
- end
253
-
254
- def load_routes
255
- require_relative "application/routes"
256
-
257
- require File.join(configuration.root, configuration.router.routes_path)
258
- routes_class = autodiscover_application_constant(configuration.router.routes_class_name)
259
- routes_class.routes
260
- rescue LoadError
261
- proc {}
262
- end
263
-
264
- def router_resolver
265
- config.router.resolver.new(
266
- slices: slices,
267
- inflector: inflector
268
- )
269
- end
270
- end
271
- # rubocop:enable Metrics/ModuleLength
272
- end
273
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/cli"
4
- require_relative "commands"
5
-
6
- module Hanami
7
- class CLI
8
- module Application
9
- # Hanami application CLI
10
- class CLI < Hanami::CLI
11
- attr_reader :application
12
-
13
- def initialize(application: nil, commands: Commands)
14
- super(commands)
15
- @application = application
16
- end
17
-
18
- private
19
-
20
- # TODO: we should make a prepare_command method upstream
21
- def parse(result, out)
22
- command, arguments = super
23
-
24
- if command.respond_to?(:with_application)
25
- # Set HANAMI_ENV before the application inits to ensure all aspects
26
- # of the boot process respect the provided env
27
- ENV["HANAMI_ENV"] = arguments[:env] if arguments[:env]
28
-
29
- require "hanami/prepare"
30
- application = Hanami.application
31
-
32
- [command.with_application(application), arguments]
33
- else
34
- [command, arguments]
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../base_command"
4
-
5
- module Hanami
6
- class CLI
7
- module Application
8
- # Hanami application CLI command (intended to run inside application directory)
9
- class Command < BaseCommand
10
- def self.inherited(klass)
11
- super
12
-
13
- klass.option :env, aliases: ["-e"], default: nil, desc: "Application environment"
14
- end
15
-
16
- attr_reader :application
17
-
18
- def initialize(application: nil, **opts)
19
- super(**opts)
20
- @application = application
21
- end
22
-
23
- def with_application(application)
24
- self.class.new(
25
- command_name: @command_name,
26
- application: application,
27
- out: out,
28
- inflector: application.inflector,
29
- files: files,
30
- )
31
- end
32
-
33
- private
34
-
35
- def run_command(klass, *args)
36
- klass.new(
37
- command_name: klass.name,
38
- application: application,
39
- out: out,
40
- inflector: application.inflector,
41
- files: files,
42
- ).call(*args)
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/cli"
4
- require "hanami/cli/application/command"
5
- require "hanami/console/context"
6
-
7
- module Hanami
8
- class CLI
9
- module Application
10
- module Commands # rubocop:disable Style/Documentation
11
- # Hanami application `console` CLI command
12
- class Console < Command
13
- REPL =
14
- begin
15
- require "pry"
16
- Pry
17
- rescue LoadError
18
- require "irb"
19
- IRB
20
- end
21
-
22
- desc "Open interactive console"
23
-
24
- def call(**)
25
- measure "#{prompt_prefix} booted in" do
26
- out.puts "=> starting #{prompt_prefix} console"
27
- application.init
28
- end
29
-
30
- start_repl
31
- end
32
-
33
- private
34
-
35
- def start_repl
36
- context = Hanami::Console::Context.new(application)
37
-
38
- case REPL.name.to_sym
39
- when :Pry
40
- start_pry(context)
41
- when :IRB
42
- start_irb(context)
43
- end
44
- end
45
-
46
- def start_pry(context)
47
- # https://github.com/pry/pry/pull/1877
48
- if Gem.loaded_specs["pry"].version >= Gem::Version.new("0.13.0")
49
- Pry.prompt = Pry::Prompt.new(:hanami, "Hanami Console prompt.", prompt_procs)
50
- Pry.start(context)
51
- else
52
- Pry.start(context, prompt_procs)
53
- end
54
- end
55
-
56
- def start_irb(context)
57
- IRB.start(context, prompt_procs)
58
- end
59
-
60
- def prompt_procs
61
- [proc { default_prompt }, proc { indented_prompt }]
62
- end
63
-
64
- def default_prompt
65
- "#{prompt_prefix}> "
66
- end
67
-
68
- def indented_prompt
69
- "#{prompt_prefix}* "
70
- end
71
-
72
- def prompt_prefix
73
- "#{inflector.underscore(application.application_name)}[#{application.config.env}]"
74
- end
75
- end
76
-
77
- register "console", Console
78
- end
79
- end
80
- end
81
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/cli/registry"
4
-
5
- module Hanami
6
- class CLI
7
- module Application
8
- # Hanami application CLI commands registry
9
- module Commands
10
- extend Hanami::CLI::Registry
11
-
12
- require_relative "commands/console"
13
- end
14
- end
15
- end
16
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dry/inflector"
4
- require "hanami/cli/command"
5
- require "hanami/utils/files"
6
-
7
- module Hanami
8
- class CLI
9
- # Base class for Hanami application CLI commands
10
- class BaseCommand < Hanami::CLI::Command
11
- attr_reader :out
12
- attr_reader :inflector
13
- attr_reader :files
14
-
15
- def initialize(
16
- command_name:,
17
- out: $stdout,
18
- inflector: Dry::Inflector.new,
19
- files: Hanami::Utils::Files
20
- )
21
- super(command_name: command_name)
22
-
23
- @out = out
24
- @inflector = inflector
25
- @files = files
26
- end
27
-
28
- private
29
-
30
- def run_command(klass, *args)
31
- klass.new(
32
- command_name: klass.name,
33
- application: application,
34
- out: out,
35
- files: files,
36
- ).call(*args)
37
- end
38
-
39
- def measure(desc)
40
- start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
41
- yield
42
- stop = Process.clock_gettime(Process::CLOCK_MONOTONIC)
43
-
44
- out.puts "=> #{desc} in #{(stop - start).round(1)}s"
45
- end
46
- end
47
- end
48
- end
@@ -1,171 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami"
4
- require "hanami/cli/command"
5
- require "concurrent"
6
- require "hanami/utils/files"
7
- require "erb"
8
-
9
- module Hanami
10
- # Hanami CLI
11
- #
12
- # @since 1.1.0
13
- class CLI
14
- module Commands
15
- # Abstract command
16
- #
17
- # @since 1.1.0
18
- class Command < Dry::CLI::Command
19
- # @since 1.1.0
20
- # @api private
21
- def self.inherited(component)
22
- super
23
-
24
- component.class_eval do
25
- @_requirements = Concurrent::Array.new
26
- extend ClassMethods
27
- prepend InstanceMethods
28
- end
29
- end
30
-
31
- # Class level interface
32
- #
33
- # @since 1.1.0
34
- module ClassMethods
35
- # Requires an internal Hanami component
36
- #
37
- # @param names [Array<String>] the name of one or more components
38
- #
39
- # @since 1.1.0
40
- #
41
- # @example
42
- # require "hanami/cli/commands"
43
- #
44
- # module HanamiDatabaseHelpers
45
- # class TruncateTables < Hanami::CLI::Commands::Command
46
- # requires "model.configuration"
47
- #
48
- # def call(*)
49
- # url = requirements["model.configuration"].url
50
- # # ...
51
- # end
52
- # end
53
- # end
54
- #
55
- # Hanami::CLI.register "db truncate", HanamiDatabaseHelpers::TruncateTables
56
- def requires(*names)
57
- requirements.concat(names)
58
- end
59
-
60
- # @since 1.1.0
61
- # @api private
62
- def requirements
63
- @_requirements
64
- end
65
- end
66
-
67
- # @since 1.1.0
68
- # @api private
69
- module InstanceMethods
70
- # @since 1.1.0
71
- # @api private
72
- def call(**options)
73
- # FIXME: merge ENV vars (like HANAMI_ENV) into **options
74
- super(options)
75
- rescue StandardError => exception
76
- warn exception.message
77
- warn exception.backtrace.join("\n\t")
78
- exit(1)
79
- end
80
- end
81
-
82
- # @since 1.1.0
83
- # @api private
84
- def initialize(command_name:, out: $stdout, files: Utils::Files)
85
- super(command_name: command_name)
86
-
87
- @out = out
88
- @files = files
89
- end
90
-
91
- private
92
-
93
- # Template renderer
94
- #
95
- # @since 1.1.0
96
- # @api private
97
- class Renderer
98
- # @since 1.1.0
99
- # @api private
100
- TRIM_MODE = "-"
101
-
102
- # @since 1.1.0
103
- # @api private
104
- def initialize
105
- freeze
106
- end
107
-
108
- # @since 1.1.0
109
- # @api private
110
- def call(template, context)
111
- ::ERB.new(template, nil, TRIM_MODE).result(context)
112
- end
113
- end
114
-
115
- # @since 1.1.0
116
- # @api private
117
- SAY_FORMATTER = "%<operation>12s %<path>s\n"
118
-
119
- # @since 1.1.0
120
- # @api private
121
- attr_reader :out
122
-
123
- # @since 1.1.0
124
- # @api private
125
- attr_reader :files
126
-
127
- # @since 1.1.0
128
- # @api private
129
- attr_reader :templates
130
-
131
- # @since 1.1.0
132
- # @api private
133
- def render(path, context)
134
- template = File.read(path)
135
- renderer = Renderer.new
136
-
137
- renderer.call(template, context.binding)
138
- end
139
-
140
- # @since 1.1.0
141
- # @api private
142
- def generate_file(source, destination, context)
143
- files.write(
144
- destination,
145
- render(source, context)
146
- )
147
- end
148
-
149
- # @since 1.1.0
150
- # @api private
151
- def say(operation, path)
152
- out.puts(SAY_FORMATTER % { operation: operation, path: path }) # rubocop:disable Style/FormatString
153
- end
154
-
155
- # @since 1.1.0
156
- # @api private
157
- def project
158
- # FIXME: is this still useful?
159
- raise "it used to be implemented as Project"
160
- end
161
-
162
- # @since 1.1.0
163
- # @api private
164
- def requirements
165
- # FIXME: require components via the new Hanami::Container
166
- raise "it used to be implemented as Hanami::Components"
167
- end
168
- end
169
- end
170
- end
171
- end