hanamismith 0.0.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +1 -2
  3. data/README.adoc +30 -10
  4. data/hanamismith.gemspec +2 -2
  5. data/lib/hanamismith/builders/bundler.rb +19 -3
  6. data/lib/hanamismith/builders/core.rb +5 -4
  7. data/lib/hanamismith/builders/environments/development.rb +33 -0
  8. data/lib/hanamismith/builders/environments/test.rb +33 -0
  9. data/lib/hanamismith/builders/rack/attack.rb +32 -0
  10. data/lib/hanamismith/builders/rack/config.rb +30 -0
  11. data/lib/hanamismith/builders/{environment.rb → refinement.rb} +8 -5
  12. data/lib/hanamismith/builders/rspec/application_shared_context.rb +34 -0
  13. data/lib/hanamismith/builders/rspec/database.rb +34 -0
  14. data/lib/hanamismith/builders/rspec/factory.rb +34 -0
  15. data/lib/hanamismith/builders/slices/health.rb +39 -0
  16. data/lib/hanamismith/builders/slices/main.rb +1 -1
  17. data/lib/hanamismith/builders/{rack.rb → stylesheet.rb} +4 -3
  18. data/lib/hanamismith/cli/actions/build.rb +10 -2
  19. data/lib/hanamismith/templates/%project_name%/Guardfile.erb +1 -1
  20. data/lib/hanamismith/templates/%project_name%/Procfile.dev.erb +1 -1
  21. data/lib/hanamismith/templates/%project_name%/app/{repo.rb.erb → repository.rb.erb} +1 -1
  22. data/lib/hanamismith/templates/%project_name%/config/app.rb.erb +3 -0
  23. data/lib/hanamismith/templates/%project_name%/config/providers/rack_attack.rb.erb +11 -0
  24. data/lib/hanamismith/templates/%project_name%/config/routes.rb.erb +2 -3
  25. data/lib/hanamismith/templates/%project_name%/config.ru.erb +3 -1
  26. data/lib/hanamismith/templates/%project_name%/env.development.erb +1 -0
  27. data/lib/hanamismith/templates/%project_name%/env.test.erb +1 -0
  28. data/lib/hanamismith/templates/%project_name%/lib/%project_path%/refinements/actions/response.rb.erb +16 -0
  29. data/lib/hanamismith/templates/%project_name%/public/stylesheets/site.css.erb +11 -0
  30. data/lib/hanamismith/templates/%project_name%/slices/health/actions/show.rb.erb +18 -0
  31. data/lib/hanamismith/templates/%project_name%/slices/main/repository.rb.erb +7 -0
  32. data/lib/hanamismith/templates/%project_name%/slices/main/templates/layouts/app.html.erb.erb +4 -18
  33. data/lib/hanamismith/templates/%project_name%/spec/hanami_helper.rb.erb +25 -3
  34. data/lib/hanamismith/templates/%project_name%/spec/lib/%project_path%/refinements/actions/response_spec.rb.erb +24 -0
  35. data/lib/hanamismith/templates/%project_name%/spec/slices/health/actions/show_spec.rb.erb +14 -0
  36. data/lib/hanamismith/templates/%project_name%/spec/support/database.rb.erb +10 -0
  37. data/lib/hanamismith/templates/%project_name%/spec/support/factory.rb.erb +6 -0
  38. data/lib/hanamismith/templates/%project_name%/spec/support/shared_contexts/application.rb.erb +3 -0
  39. data.tar.gz.sig +0 -0
  40. metadata +27 -9
  41. metadata.gz.sig +2 -2
  42. data/lib/hanamismith/templates/%project_name%/envrc.erb +0 -1
  43. data/lib/hanamismith/templates/%project_name%/slices/main/repo.rb.erb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1547f2b3305d29362da3bfc4779fd1093aba4834ddf8ab7a09d684722325b708
4
- data.tar.gz: 9b83495269ac455d6eca644ff635127746bef385bda1ce0593a389cdfe421175
3
+ metadata.gz: cf1e7802201b63905939929ff7014adcd106767ffdb951e2a8a312ec6abfeb2a
4
+ data.tar.gz: 8720f041a7d69d3eed3307f156941a0e444a952c711169decc588b4e6612ece4
5
5
  SHA512:
6
- metadata.gz: c351b54ab430d6c0f54e5b9bfa562fc052bd532ac1f95af6d9ddac58a957d49330eb5da490336fc2e72ad245fef324965fd05a25c633845c2f3dea0a40fb6c70
7
- data.tar.gz: 73767e229d91778bb6f21df1edf5cafebd94794c9f7ae97471eaca9876fe0d39cd242cb1b70f194af067a3cf1c3511f2445a7a5f36f28119eb0ab8716b09ba72
6
+ metadata.gz: 336891443203d370011c047e118882edfc37e3f2e2e0c4b48331613b96d7837a5896dcc7123384ba15e7294dc464cc07a5ed809e5e918918f9a7fc86581fa10c
7
+ data.tar.gz: fd075996ec4289fdc853a0c9fd3836f028a5527d413b498ac2f4ed09ffcb27969cf86697cadd566acecbfa5e0c36047145199b630d961486a8380636383d70ae
checksums.yaml.gz.sig CHANGED
@@ -1,2 +1 @@
1
- ,H~kjyi��4��t������a�Ը��Ц�::{�Y��n+
2
- C�V{%,�b�ea�Zz�i,��}S,�t̲���, Y���#��o�=���񿅀4��:�ֻ,b3����Z��F^�z20�e�=<�`8���W�Z�鼾�y[��-�����$;z���#�i�'�ٴi[������l���o�#�<M��k�~�%�B�=��5��������栿N6���Ld�j0k�x��0�lF�%�ځ2q? �
1
+ ���>E��]mjc@'��V1e���f\o5M��w;F��N)lYuK�3�P�J���M�Fhl�!�4z2,zC�Ӿ_�^-�^�Pa��e��߷Y�u�RK� ����e I�/S�vl�w?����}�൩�E��'�x�y)8��^�C�1����qЫ����Ņ��:ց��'���߰�[�D���{�'x�c�<_|�y޻�7e[
data/README.adoc CHANGED
@@ -2,16 +2,22 @@
2
2
  :toclevels: 5
3
3
  :figure-caption!:
4
4
 
5
+ :capybara_link: link:https://github.com/teamcapybara/capybara[Capybara]
5
6
  :cuprite_link: link:https://cuprite.rubycdp.com[Cuprite]
6
7
  :dry_link: link:https://dry-rb.org[Dry RB]
8
+ :dotenv_link: link:https://github.com/bkeepers/dotenv[Dotenv]
7
9
  :dotfiles_link: link:https://www.alchemists.io/projects/dotfiles[Dotfiles]
8
10
  :hanami_link: link:https://hanamirb.org[Hanami]
9
11
  :htmx_link: link:https://htmx.org[HTMX]
12
+ :pg_link: link:https://github.com/ged/ruby-pg[pg]
13
+ :puma_link: link:https://puma.io[Puma]
14
+ :rack_link: link:https://github.com/rack/rack[Rack]
15
+ :rom_link: link:https://rom-rb.org[ROM]
10
16
  :rubysmith_link: link:https://www.alchemists.io/projects/rubysmith[Rubysmith]
11
17
 
12
18
  = Hanamismith
13
19
 
14
- Hanamismith is a Command Line Interface (CLI) for smithing Hanami projects. Perfect for when you need a professional and robust tool for building new project skeletons. To quote from the {dry_link} and {hanami_link} team:
20
+ Hanamismith is a Command Line Interface (CLI) for smithing Hanami projects. Perfect for when you need a professional and robust tool for building new project skeletons. To quote from the {dry_link} and {hanami_link} teams:
15
21
  ____
16
22
  If you're looking for new ways to build maintainable, secure, faster and testable Ruby applications, you're in for a treat. *Hanami is built for people like you*.
17
23
 
@@ -24,11 +30,15 @@ toc::[]
24
30
 
25
31
  == Features
26
32
 
27
- * Supports all {rubysmith_link} features.
28
- * Supports {dry_link} functional programming.
29
- * Supports {hanami_link} for web application development.
30
- * Supports {htmx_link} for proper REST (hypermedia) architectures (i.e. HTML over the wire) so you can write less code and avoid bloated JavaScript stacks.
31
- * Supports {cuprite_link} for full, headless, feature testing.
33
+ * Built atop {rubysmith_link} and leverages all features.
34
+ * Uses {dry_link} functional programming.
35
+ * Uses {hanami_link} for web application development.
36
+ * Uses {htmx_link} for proper REST (hypermedia) architectures (i.e. HTML over the wire) so you can write less code and avoid bloated JavaScript stacks.
37
+ * Uses {pg_link} coupled with {rom_link} for database management.
38
+ * Uses {rack_link}, specifically: `Rack::Deflater`, `Rack::Static`, and link:https://github.com/rack/rack-attack[Rack::Attack].
39
+ * Uses {puma_link} as the default web server and fully configured for local and production environments.
40
+ * Uses {capybara_link} with {cuprite_link} (driver) for full, headless, feature testing.
41
+ * Uses {dotenv_link} for managing your environment configurations.
32
42
 
33
43
  == Requirements
34
44
 
@@ -128,7 +138,10 @@ hanamismith --build demo
128
138
 
129
139
  # Run code quality and test coverage checks
130
140
  cd demo
131
- bundle exec rake
141
+ bin/setup
142
+ hanami db create
143
+ HANAMI_ENV=test hanami db create
144
+ bin/rake
132
145
 
133
146
  # Develop (red, green, refactor)
134
147
  bin/guard
@@ -138,12 +151,17 @@ git commit # (repeat until finished with implementation)
138
151
  overmind start --port-step 10 --procfile Procfile.dev
139
152
 
140
153
  # Run: Without Overmind
141
- hanami start
154
+ hanami server
142
155
 
143
156
  # Deploy
144
157
  git push
145
158
  ----
146
159
 
160
+ Once the server is running you can visit (or ping) the following endpoints:
161
+
162
+ * `/`: The default welcome page.
163
+ * `/status`: The health status of the application. This will be _green_ (200 OK) when the server is up or _red_ (503 Service Unavailable) when the server is down.
164
+
147
165
  === Aliases
148
166
 
149
167
  For link:https://www.gnu.org/software/bash[Bash] users -- or other shell users -- you might find the following aliases helpful in reducing terminal keystrokes when using this gem:
@@ -159,7 +177,9 @@ The above is what I use via my {dotfiles_link} project.
159
177
 
160
178
  === Demonstration
161
179
 
162
- If you'd like a fully working demonstration appliation -- as built by this gem -- then check ouh the link:https://github.com/bkuhlmann/hemo[Hemo] project.
180
+ If you'd like a fully working demonstration application -- as built by this gem -- then check out the link:https://github.com/bkuhlmann/hemo[Hemo] project. Here's a quick screencast overview of demonstration application:
181
+
182
+ video::https://www.alchemists.io/videos/projects/hemo/demo.mp4[poster=https://www.alchemists.io/images/projects/hemo/demo.png,width=1028,height=854,role=focal_point]
163
183
 
164
184
  == Development
165
185
 
@@ -185,7 +205,7 @@ To test, run:
185
205
 
186
206
  [source,bash]
187
207
  ----
188
- bundle exec rake
208
+ bin/rake
189
209
  ----
190
210
 
191
211
  == link:https://www.alchemists.io/policies/license[License]
data/hanamismith.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "hanamismith"
5
- spec.version = "0.0.0"
5
+ spec.version = "0.2.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://www.alchemists.io/projects/hanamismith"
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_dependency "hanami", "~> 2.0"
31
31
  spec.add_dependency "infusible", "~> 1.0"
32
32
  spec.add_dependency "refinements", "~> 10.0"
33
- spec.add_dependency "rubysmith", "~> 4.3"
33
+ spec.add_dependency "rubysmith", "~> 4.4"
34
34
  spec.add_dependency "runcom", "~> 9.0"
35
35
  spec.add_dependency "spek", "~> 1.0"
36
36
  spec.add_dependency "zeitwerk", "~> 2.6"
@@ -16,6 +16,7 @@ module Hanamismith
16
16
  alter_groups
17
17
  append_development_group
18
18
  append_test_group
19
+ insert_development_and_test_group
19
20
  remove_zeitwerk
20
21
  configuration
21
22
  end
@@ -30,6 +31,7 @@ module Hanamismith
30
31
  .insert_after("source", %(gem "erbse", "~> 0.1"\n))
31
32
  .insert_after("source", %(gem "hanami", "~> 2.0"\n))
32
33
  .insert_after("source", %(gem "hanami-controller", "~> 2.0"\n))
34
+ .insert_after("source", %(gem "hanami-helpers", "~> 0.0"\n))
33
35
  .insert_after("source", %(gem "hanami-router", "~> 2.0"\n))
34
36
  .insert_after("source", %(gem "hanami-validations", "~> 2.0"\n))
35
37
  .insert_after(
@@ -37,6 +39,7 @@ module Hanamismith
37
39
  %(gem "hanami-view", github: "hanami/view", branch: "main"\n)
38
40
  )
39
41
  .insert_after("source", %(gem "puma", "~> 6.0"\n))
42
+ .insert_after("source", %(gem "rack-attack", "~> 6.6"\n))
40
43
  end
41
44
  # rubocop:enable Metrics/MethodLength
42
45
 
@@ -49,10 +52,12 @@ module Hanamismith
49
52
 
50
53
  def alter_groups
51
54
  with_template.insert_after(/group :code_quality/, %( gem "rubocop-sequel", "~> 0.3"\n))
52
- .insert_after(/group :development/, %( gem "localhost", "~> 1.1"\n))
53
- .insert_after(/group :development/, %( gem "rerun", "~> 0.14"\n))
55
+ .insert_after(/group :development do/, %( gem "localhost", "~> 1.1"\n))
56
+ .insert_after(/group :development do/, %( gem "rerun", "~> 0.14"\n))
54
57
  .insert_after(/group :test/, %( gem "capybara", "~> 3.38"\n))
55
58
  .insert_after(/group :test/, %( gem "cuprite", "~> 0.14"\n))
59
+ .insert_after(/group :test/, %( gem "database_cleaner-sequel", "~> 2.0"\n))
60
+ .insert_after(/group :test/, %( gem "launchy", "~> 2.5"\n))
56
61
  .insert_after(/group :test/, %( gem "rack-test", "~> 2.0"\n))
57
62
  .insert_after(/group :test/, %( gem "rom-factory", "~> 0.11"\n))
58
63
  .replace(/gem "rspec.+/, %(gem "hanami-rspec", "~> 2.0"))
@@ -62,7 +67,6 @@ module Hanamismith
62
67
  return if configuration.markdown? || configuration.build_rake || configuration.build_yard
63
68
 
64
69
  with_template.append <<~CONTENT
65
-
66
70
  group :development do
67
71
  gem "localhost", "~> 1.1"
68
72
  gem "rerun", "~> 0.14"
@@ -78,13 +82,25 @@ module Hanamismith
78
82
  group :test do
79
83
  gem "capybara", "~> 3.38"
80
84
  gem "cuprite", "~> 0.14"
85
+ gem "database_cleaner-sequel", "~> 2.0"
81
86
  gem "hanami-rspec", "~> 2.0"
87
+ gem "launchy", "~> 2.5"
82
88
  gem "rack-test", "~> 2.0"
83
89
  gem "rom-factory", "~> 0.11"
84
90
  end
85
91
  CONTENT
86
92
  end
87
93
 
94
+ def insert_development_and_test_group
95
+ with_template.insert_before(/group :development/, <<~CONTENT)
96
+
97
+ group :development, :test do
98
+ gem "dotenv", "~> 2.8"
99
+ end
100
+
101
+ CONTENT
102
+ end
103
+
88
104
  def remove_zeitwerk = with_template.replace(/.+zeitwerk.+\n\n/, "\n")
89
105
 
90
106
  def with_template
@@ -24,15 +24,16 @@ module Hanamismith
24
24
 
25
25
  attr_reader :configuration, :builder
26
26
 
27
- def add_application_action
27
+ def add_action
28
28
  builder.call(configuration.merge(template_path: "%project_name%/app/action.rb.erb")).render
29
29
  end
30
30
 
31
- def add_application_repository
32
- builder.call(configuration.merge(template_path: "%project_name%/app/repo.rb.erb")).render
31
+ def add_repository
32
+ builder.call(configuration.merge(template_path: "%project_name%/app/repository.rb.erb"))
33
+ .render
33
34
  end
34
35
 
35
- def add_application_view
36
+ def add_view
36
37
  builder.call(configuration.merge(template_path: "%project_name%/app/view.rb.erb")).render
37
38
  end
38
39
 
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Hanamismith
6
+ module Builders
7
+ module Environments
8
+ # Builds development environment skeleton.
9
+ class Development
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration, builder: Rubysmith::Builder
15
+ @configuration = configuration
16
+ @builder = builder
17
+ end
18
+
19
+ def call
20
+ builder.call(configuration.merge(template_path: "%project_name%/env.development.erb"))
21
+ .render
22
+ .rename(".env.development")
23
+
24
+ configuration
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :configuration, :builder
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Hanamismith
6
+ module Builders
7
+ module Environments
8
+ # Builds test environment skeleton.
9
+ class Test
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration, builder: Rubysmith::Builder
15
+ @configuration = configuration
16
+ @builder = builder
17
+ end
18
+
19
+ def call
20
+ builder.call(configuration.merge(template_path: "%project_name%/env.test.erb"))
21
+ .render
22
+ .rename(".env.test")
23
+
24
+ configuration
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :configuration, :builder
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Hanamismith
6
+ module Builders
7
+ module Rack
8
+ # Builds project skeleton with Rack Attack provider.
9
+ class Attack
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration, builder: Rubysmith::Builder
15
+ @configuration = configuration
16
+ @builder = builder
17
+ end
18
+
19
+ def call
20
+ path = "%project_name%/config/providers/rack_attack.rb.erb"
21
+ builder.call(configuration.merge(template_path: path)).render
22
+
23
+ configuration
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :configuration, :builder
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Hanamismith
6
+ module Builders
7
+ module Rack
8
+ # Builds project skeleton Rack support.
9
+ class Config
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration, builder: Rubysmith::Builder
15
+ @configuration = configuration
16
+ @builder = builder
17
+ end
18
+
19
+ def call
20
+ builder.call(configuration.merge(template_path: "%project_name%/config.ru.erb")).render
21
+ configuration
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :configuration, :builder
27
+ end
28
+ end
29
+ end
30
+ end
@@ -4,8 +4,8 @@ require "refinements/structs"
4
4
 
5
5
  module Hanamismith
6
6
  module Builders
7
- # Builds project environment skeleton.
8
- class Environment
7
+ # Builds project skeleton foundation.
8
+ class Refinement
9
9
  using Refinements::Structs
10
10
 
11
11
  def self.call(...) = new(...).call
@@ -16,9 +16,12 @@ module Hanamismith
16
16
  end
17
17
 
18
18
  def call
19
- builder.call(configuration.merge(template_path: "%project_name%/envrc.erb"))
20
- .render
21
- .rename(".envrc")
19
+ %w[
20
+ %project_name%/lib/%project_path%/refinements/actions/response.rb.erb
21
+ %project_name%/spec/lib/%project_path%/refinements/actions/response_spec.rb.erb
22
+ ].each do |path|
23
+ builder.call(configuration.merge(template_path: path)).render
24
+ end
22
25
 
23
26
  configuration
24
27
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Hanamismith
6
+ module Builders
7
+ module RSpec
8
+ # Builds project skeleton RSpec application shared context.
9
+ class ApplicationSharedContext
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration, builder: Rubysmith::Builder
15
+ @configuration = configuration
16
+ @builder = builder
17
+ end
18
+
19
+ def call
20
+ return configuration unless configuration.build_rspec
21
+
22
+ path = "%project_name%/spec/support/shared_contexts/application.rb.erb"
23
+ builder.call(configuration.merge(template_path: path)).render
24
+
25
+ configuration
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :configuration, :builder
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Hanamismith
6
+ module Builders
7
+ module RSpec
8
+ # Builds project skeleton RSpec application database support.
9
+ class Database
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration, builder: Rubysmith::Builder
15
+ @configuration = configuration
16
+ @builder = builder
17
+ end
18
+
19
+ def call
20
+ return configuration unless configuration.build_rspec
21
+
22
+ path = "%project_name%/spec/support/database.rb.erb"
23
+ builder.call(configuration.merge(template_path: path)).render
24
+
25
+ configuration
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :configuration, :builder
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Hanamismith
6
+ module Builders
7
+ module RSpec
8
+ # Builds project skeleton RSpec application database support.
9
+ class Factory
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration, builder: Rubysmith::Builder
15
+ @configuration = configuration
16
+ @builder = builder
17
+ end
18
+
19
+ def call
20
+ return configuration unless configuration.build_rspec
21
+
22
+ path = "%project_name%/spec/support/factory.rb.erb"
23
+ builder.call(configuration.merge(template_path: path)).render
24
+
25
+ configuration
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :configuration, :builder
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Hanamismith
6
+ module Builders
7
+ module Slices
8
+ # Builds project health slice skeleton.
9
+ class Health
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration, builder: Rubysmith::Builder
15
+ @configuration = configuration
16
+ @builder = builder
17
+ end
18
+
19
+ def call
20
+ add_action
21
+ configuration
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :configuration, :builder
27
+
28
+ def add_action
29
+ %w[
30
+ %project_name%/slices/health/actions/show.rb.erb
31
+ %project_name%/spec/slices/health/actions/show_spec.rb.erb
32
+ ].each do |path|
33
+ builder.call(configuration.merge(template_path: path)).render
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -31,7 +31,7 @@ module Hanamismith
31
31
  end
32
32
 
33
33
  def add_repository
34
- path = "%project_name%/slices/main/repo.rb.erb"
34
+ path = "%project_name%/slices/main/repository.rb.erb"
35
35
  builder.call(configuration.merge(template_path: path)).render
36
36
  end
37
37
 
@@ -4,8 +4,8 @@ require "refinements/structs"
4
4
 
5
5
  module Hanamismith
6
6
  module Builders
7
- # Builds project skeleton Rack support.
8
- class Rack
7
+ # Builds project skeleton stylesheet.
8
+ class Stylesheet
9
9
  using Refinements::Structs
10
10
 
11
11
  def self.call(...) = new(...).call
@@ -16,7 +16,8 @@ module Hanamismith
16
16
  end
17
17
 
18
18
  def call
19
- builder.call(configuration.merge(template_path: "%project_name%/config.ru.erb")).render
19
+ path = "%project_name%/public/stylesheets/site.css.erb"
20
+ builder.call(configuration.merge(template_path: path)).render
20
21
  configuration
21
22
  end
22
23
 
@@ -10,7 +10,10 @@ module Hanamismith
10
10
  # Order is important.
11
11
  BUILDERS = [
12
12
  Builders::Core,
13
+ Builders::Refinement,
14
+ Builders::Stylesheet,
13
15
  Builders::Slices::Main,
16
+ Builders::Slices::Health,
14
17
  Rubysmith::Builders::Version,
15
18
  Builders::Documentation::Readme,
16
19
  Rubysmith::Builders::Documentation::Citation,
@@ -30,9 +33,13 @@ module Hanamismith
30
33
  Rubysmith::Builders::Reek,
31
34
  Rubysmith::Builders::RSpec::Binstub,
32
35
  Rubysmith::Builders::RSpec::Context,
36
+ Builders::RSpec::ApplicationSharedContext,
37
+ Builders::RSpec::Database,
38
+ Builders::RSpec::Factory,
33
39
  Builders::RSpec::Helper,
34
40
  Builders::RSpec::Hanami,
35
- Builders::Rack,
41
+ Builders::Rack::Config,
42
+ Builders::Rack::Attack,
36
43
  Builders::Puma::Configuration,
37
44
  Builders::Puma::Procfile,
38
45
  Builders::Caliber,
@@ -40,7 +47,8 @@ module Hanamismith
40
47
  Rubysmith::Extensions::Pragmater,
41
48
  Rubysmith::Extensions::Tocer,
42
49
  Rubysmith::Extensions::Rubocop,
43
- Builders::Environment,
50
+ Builders::Environments::Development,
51
+ Builders::Environments::Test,
44
52
  Builders::Git::Commit
45
53
  ].freeze
46
54
 
@@ -1,4 +1,4 @@
1
- guard :rspec, cmd: "NO_COVERAGE=true bundle exec rspec --format documentation" do
1
+ guard :rspec, cmd: "NO_COVERAGE=true bin/rspec --format documentation" do
2
2
  require "guard/rspec/dsl"
3
3
 
4
4
  dsl = Guard::RSpec::Dsl.new self
@@ -1 +1 @@
1
- web: rerun --pattern="**/*.{css,erb,js,rb}" -- bundle exec puma --config ./config/puma.rb
1
+ web: rerun --dir app,config,lib,slices --pattern="**/*.{css,erb,js,rb}" -- bundle exec puma --config ./config/puma.rb
@@ -4,7 +4,7 @@ require "rom-repository"
4
4
 
5
5
  <% namespace do %>
6
6
  # The application repository.
7
- class Repo < ROM::Repository::Root
7
+ class Repository < ROM::Repository::Root
8
8
  include Deps[container: "persistence.rom"]
9
9
  end
10
10
  <% end %>
@@ -4,5 +4,8 @@ require "hanami"
4
4
  # Handles HTTP requests.
5
5
  class App < Hanami::App
6
6
  config.actions.content_security_policy[:script_src] = "https://unpkg.com"
7
+
8
+ config.middleware.use Rack::Deflater
9
+ config.middleware.use Rack::Static, {urls: %w[/stylesheets javascript], root: "public"}
7
10
  end
8
11
  <% end %>
@@ -0,0 +1,11 @@
1
+ Hanami.app.register_provider :rack_attack do
2
+ prepare { require "rack/attack" }
3
+
4
+ start do
5
+ Rack::Attack.safelist "allow from localhost" do |request|
6
+ %w[127.0.0.1 ::1].include? request.ip
7
+ end
8
+
9
+ Rack::Attack.throttle("requests by IP", limit: 100, period: 60, &:ip)
10
+ end
11
+ end
@@ -1,8 +1,7 @@
1
1
  <% namespace do %>
2
2
  # Configures application routes.
3
3
  class Routes < Hanami::Routes
4
- slice :main, at: "/" do
5
- root to: "home.show"
6
- end
4
+ slice(:health, at: "/status") { root to: "show" }
5
+ slice(:main, at: "/") { root to: "home.show" }
7
6
  end
8
7
  <% end %>
@@ -1,4 +1,6 @@
1
1
  require "hanami/boot"
2
2
  Bundler.require :tools if Hanami.env? :development
3
3
 
4
- run Hanami.app
4
+ app = Rack::Builder.app { run Hanami.app }
5
+
6
+ run app
@@ -0,0 +1 @@
1
+ DATABASE_URL=postgres://localhost/<%= configuration.project_name %>_development
@@ -0,0 +1 @@
1
+ DATABASE_URL=postgres://localhost/<%= configuration.project_name %>_test
@@ -0,0 +1,16 @@
1
+ <% namespace do %>
2
+ module Refinements
3
+ module Actions
4
+ # Modifies and enhances default Hanami action response behavior.
5
+ module Response
6
+ refine Hanami::Action::Response do
7
+ def with body:, status:
8
+ @body = [body]
9
+ @status = status
10
+ self
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ <% end %>
@@ -0,0 +1,11 @@
1
+ :root {
2
+ --site-font-family: Verdana;
3
+ }
4
+
5
+ .page {
6
+ align-items: center;
7
+ display: flex;
8
+ flex-direction: column;
9
+ font-family: var(--site-font-family);
10
+ margin: 1rem 5rem;
11
+ }
@@ -0,0 +1,18 @@
1
+ module Health
2
+ module Actions
3
+ # The show action.
4
+ class Show < <%= configuration.project_namespaced_class %>::Action
5
+ using <%= configuration.project_namespaced_class %>::Refinements::Actions::Response
6
+
7
+ handle_exception Exception => :down
8
+
9
+ def handle(*, response) = response.with body: body(:green), status: 200
10
+
11
+ private
12
+
13
+ def down(*, response, _exception) = response.with body: body(:red), status: 503
14
+
15
+ def body(color) = %(<html><body style="background-color: #{color}"></body></html>)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ # auto_register: false
2
+
3
+ module Main
4
+ # The main repository.
5
+ class Repository < <%= configuration.project_namespaced_class %>::Repository
6
+ end
7
+ end
@@ -4,29 +4,15 @@
4
4
  <title><%= configuration.project_label %></title>
5
5
  <meta name="viewport" content="width=device-width,initial-scale=1">
6
6
 
7
- <style type="text/css">
8
- :root {
9
- --site-font-family: Verdana;
10
- --site-color-black: hsl(0, 0%, 0%);
11
- --site-color-white: hsl(0, 0%, 100%);
12
- }
7
+ <link title="<%= configuration.project_label %> - Stylesheet" rel="stylesheet" href="/stylesheets/site.css" type="text/css">
13
8
 
14
- body {
15
- align-items: center;
16
- display: flex;
17
- flex-direction: column;
18
- font-family: var(--site-font-family);
19
- margin: 1rem 5rem;
20
- }
21
- </style>
22
-
23
- <script src="https://unpkg.com/htmx.org@1.8.4/dist/htmx.min.js"
9
+ <script src="https://unpkg.com/htmx.org@1.8.5"
24
10
  crossorigin="anonymous"
25
- integrity="sha384-wg5Y/JwF7VxGk4zLsJEcAojRtlVp1FKKdGy1qN+OMtdq72WRvX/EdRdqg/LOhYeV">
11
+ integrity="sha384-7aHh9lqPYGYZ7sTHvzP1t3BAfLhYSTy9ArHdP3Xsr9/3TlGurYgcPBoFmXX2TX/w">
26
12
  </script>
27
13
  </head>
28
14
 
29
- <body>
15
+ <body class="page">
30
16
  <!-- yield -->
31
17
  </body>
32
18
  </html>
@@ -1,22 +1,44 @@
1
1
  require "capybara/cuprite"
2
2
  require "capybara/rspec"
3
+ require "database_cleaner/sequel"
3
4
  require "rack/test"
4
5
  require "spec_helper"
5
6
 
6
7
  ENV["HANAMI_ENV"] = "test"
8
+
7
9
  require "hanami/prepare"
10
+ require_relative "support/database"
11
+ require_relative "support/factory"
12
+
13
+ using Refinements::Pathnames
8
14
 
15
+ Capybara.app = Hanami.app
9
16
  Capybara.server = :puma, {Silent: true}
10
17
  Capybara.javascript_driver = :cuprite
18
+ Capybara.save_path = Hanami.app.root.join "tmp/capybara"
11
19
  Capybara.register_driver :cuprite do |app|
12
20
  Capybara::Cuprite::Driver.new app, window_size: [1200, 800]
13
21
  end
14
22
 
15
- RSpec.shared_context "with Hanami application" do
16
- let(:app) { Hanami.app }
17
- end
23
+ DatabaseCleaner[:sequel].strategy = :transaction
24
+
25
+ Pathname.require_tree SPEC_ROOT, "support/factories/**/*.rb"
18
26
 
19
27
  RSpec.configure do |config|
28
+ config.include Capybara::DSL, Capybara::RSpecMatchers, :web
20
29
  config.include Rack::Test::Methods, type: :request
30
+ config.include Test::Database, :db
21
31
  config.include_context "with Hanami application", type: :request
32
+
33
+ config.before :suite do
34
+ Hanami.app.start :persistence
35
+ DatabaseCleaner[:sequel].clean_with :truncation
36
+ end
37
+
38
+ config.prepend_before :each, :db do |example|
39
+ DatabaseCleaner[:sequel].strategy = example.metadata[:js] ? :truncation : :transaction
40
+ DatabaseCleaner[:sequel].start
41
+ end
42
+
43
+ config.append_after(:each, :db) { DatabaseCleaner[:sequel].clean }
22
44
  end
@@ -0,0 +1,24 @@
1
+ require "hanami_helper"
2
+
3
+ RSpec.describe <%= configuration.project_namespaced_class %>::Refinements::Actions::Response do
4
+ using described_class
5
+
6
+ subject(:response) { Hanami::Action::Response.new request:, config: {} }
7
+
8
+ let :request do
9
+ Rack::MockRequest.env_for("/").then { |env| Hanami::Action::Request.new env:, params: {} }
10
+ end
11
+
12
+ describe "#with" do
13
+ it "answers response with given body and status" do
14
+ expect(response.with(body: "Danger!", status: 400)).to have_attributes(
15
+ body: ["Danger!"],
16
+ status: 400
17
+ )
18
+ end
19
+
20
+ it "answers itself" do
21
+ expect(response.with(body: "Danger!", status: 400)).to be_a(Hanami::Action::Response)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ require "hanami_helper"
2
+
3
+ RSpec.describe Health::Actions::Show do
4
+ subject(:action) { described_class.new }
5
+
6
+ describe "#call" do
7
+ it "answers 200 OK status with green background" do
8
+ expect(action.call({})).to have_attributes(
9
+ body: [%(<html><body style="background-color: green"></body></html>)],
10
+ status: 200
11
+ )
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module Test
2
+ # Provides convenience methods for testing purposes.
3
+ module Database
4
+ def self.relations = rom.relations
5
+
6
+ def self.rom = Hanami.app["persistence.rom"]
7
+
8
+ def self.db = Hanami.app["persistence.db"]
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ require "rom-factory"
2
+ require_relative "database"
3
+
4
+ module Test
5
+ Factory = ROM::Factory.configure { |config| config.rom = Test::Database.rom }
6
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.shared_context "with Hanami application" do
2
+ let(:app) { Hanami.app }
3
+ end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanamismith
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -28,7 +28,7 @@ cert_chain:
28
28
  CxDe2+VuChj4I1nvIHdu+E6XoEVlanUPKmSg6nddhkKn2gC45Kyzh6FZqnzH/CRp
29
29
  RFE=
30
30
  -----END CERTIFICATE-----
31
- date: 2023-01-18 00:00:00.000000000 Z
31
+ date: 2023-01-22 00:00:00.000000000 Z
32
32
  dependencies:
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: cogger
@@ -134,14 +134,14 @@ dependencies:
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: '4.3'
137
+ version: '4.4'
138
138
  type: :runtime
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: '4.3'
144
+ version: '4.4'
145
145
  - !ruby/object:Gem::Dependency
146
146
  name: runcom
147
147
  requirement: !ruby/object:Gem::Requirement
@@ -205,16 +205,24 @@ files:
205
205
  - lib/hanamismith/builders/console.rb
206
206
  - lib/hanamismith/builders/core.rb
207
207
  - lib/hanamismith/builders/documentation/readme.rb
208
- - lib/hanamismith/builders/environment.rb
208
+ - lib/hanamismith/builders/environments/development.rb
209
+ - lib/hanamismith/builders/environments/test.rb
209
210
  - lib/hanamismith/builders/git/commit.rb
210
211
  - lib/hanamismith/builders/guard.rb
211
212
  - lib/hanamismith/builders/puma/configuration.rb
212
213
  - lib/hanamismith/builders/puma/procfile.rb
213
- - lib/hanamismith/builders/rack.rb
214
+ - lib/hanamismith/builders/rack/attack.rb
215
+ - lib/hanamismith/builders/rack/config.rb
214
216
  - lib/hanamismith/builders/rake.rb
217
+ - lib/hanamismith/builders/refinement.rb
218
+ - lib/hanamismith/builders/rspec/application_shared_context.rb
219
+ - lib/hanamismith/builders/rspec/database.rb
220
+ - lib/hanamismith/builders/rspec/factory.rb
215
221
  - lib/hanamismith/builders/rspec/hanami.rb
216
222
  - lib/hanamismith/builders/rspec/helper.rb
223
+ - lib/hanamismith/builders/slices/health.rb
217
224
  - lib/hanamismith/builders/slices/main.rb
225
+ - lib/hanamismith/builders/stylesheet.rb
218
226
  - lib/hanamismith/cli/actions/build.rb
219
227
  - lib/hanamismith/cli/actions/config.rb
220
228
  - lib/hanamismith/cli/actions/container.rb
@@ -231,25 +239,35 @@ files:
231
239
  - lib/hanamismith/templates/%project_name%/Procfile.dev.erb
232
240
  - lib/hanamismith/templates/%project_name%/Procfile.erb
233
241
  - lib/hanamismith/templates/%project_name%/app/action.rb.erb
234
- - lib/hanamismith/templates/%project_name%/app/repo.rb.erb
242
+ - lib/hanamismith/templates/%project_name%/app/repository.rb.erb
235
243
  - lib/hanamismith/templates/%project_name%/app/view.rb.erb
236
244
  - lib/hanamismith/templates/%project_name%/bin/hanami.erb
237
245
  - lib/hanamismith/templates/%project_name%/config.ru.erb
238
246
  - lib/hanamismith/templates/%project_name%/config/app.rb.erb
239
247
  - lib/hanamismith/templates/%project_name%/config/providers/persistence.rb.erb
248
+ - lib/hanamismith/templates/%project_name%/config/providers/rack_attack.rb.erb
240
249
  - lib/hanamismith/templates/%project_name%/config/puma.rb.erb
241
250
  - lib/hanamismith/templates/%project_name%/config/routes.rb.erb
242
251
  - lib/hanamismith/templates/%project_name%/config/settings.rb.erb
243
- - lib/hanamismith/templates/%project_name%/envrc.erb
252
+ - lib/hanamismith/templates/%project_name%/env.development.erb
253
+ - lib/hanamismith/templates/%project_name%/env.test.erb
254
+ - lib/hanamismith/templates/%project_name%/lib/%project_path%/refinements/actions/response.rb.erb
244
255
  - lib/hanamismith/templates/%project_name%/lib/%project_path%/types.rb.erb
256
+ - lib/hanamismith/templates/%project_name%/public/stylesheets/site.css.erb
257
+ - lib/hanamismith/templates/%project_name%/slices/health/actions/show.rb.erb
245
258
  - lib/hanamismith/templates/%project_name%/slices/main/action.rb.erb
246
259
  - lib/hanamismith/templates/%project_name%/slices/main/actions/home/show.rb.erb
247
- - lib/hanamismith/templates/%project_name%/slices/main/repo.rb.erb
260
+ - lib/hanamismith/templates/%project_name%/slices/main/repository.rb.erb
248
261
  - lib/hanamismith/templates/%project_name%/slices/main/templates/home/show.html.erb.erb
249
262
  - lib/hanamismith/templates/%project_name%/slices/main/templates/layouts/app.html.erb.erb
250
263
  - lib/hanamismith/templates/%project_name%/slices/main/view.rb.erb
251
264
  - lib/hanamismith/templates/%project_name%/slices/main/views/home/show.rb.erb
252
265
  - lib/hanamismith/templates/%project_name%/spec/hanami_helper.rb.erb
266
+ - lib/hanamismith/templates/%project_name%/spec/lib/%project_path%/refinements/actions/response_spec.rb.erb
267
+ - lib/hanamismith/templates/%project_name%/spec/slices/health/actions/show_spec.rb.erb
268
+ - lib/hanamismith/templates/%project_name%/spec/support/database.rb.erb
269
+ - lib/hanamismith/templates/%project_name%/spec/support/factory.rb.erb
270
+ - lib/hanamismith/templates/%project_name%/spec/support/shared_contexts/application.rb.erb
253
271
  homepage: https://www.alchemists.io/projects/hanamismith
254
272
  licenses:
255
273
  - Hippocratic-2.1
metadata.gz.sig CHANGED
@@ -1,2 +1,2 @@
1
- �FL�U��*�#��YR?�By#�^��ĵb�ꬣ��8kV��a�ӭI��?�z<��b m�M#9H�dW�}�H�شu�c����g���Fq���%,��(.Ȏ�Wy ēpz�|'h��B!Ki�&� ��k"Ŋ ���o��;���s5n-iOi��rW����O���/u�ߎ\s
2
- U��W�
1
+ ~`��b(��n�֙Z�B65�aDΔ1 gos����Н)�ÑȬ�8;�Pi0~��P���Ƙ�i�C���rN90U�>�]`��E�\�j�+�{��F��o�32.BP
2
+ f�:�����G�#D;��|���| ���,Z�05��Ps�C�fZy[7W���A#4���0#�Y�"A�U��Q2�C��*�;P�)��iς��:����R�4/��F�R?*��z�v�L�Fz�#�FR�i@ti�_p�&U��Q
@@ -1 +0,0 @@
1
- export DATABASE_URL=postgres://localhost/<%= configuration.project_name %>_development
@@ -1,7 +0,0 @@
1
- # auto_register: false
2
-
3
- module Main
4
- # The main repository.
5
- class Repo < <%= configuration.project_namespaced_class %>::Repo
6
- end
7
- end