hanami-cli 2.1.0.beta1 → 2.1.0.rc1

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/Gemfile +5 -2
  4. data/hanami-cli.gemspec +1 -1
  5. data/lib/hanami/cli/bundler.rb +19 -5
  6. data/lib/hanami/cli/command.rb +4 -4
  7. data/lib/hanami/cli/commands/app/assets/command.rb +69 -0
  8. data/lib/hanami/cli/commands/app/assets/compile.rb +32 -0
  9. data/lib/hanami/cli/commands/app/assets/watch.rb +32 -0
  10. data/lib/hanami/cli/commands/app/assets.rb +16 -0
  11. data/lib/hanami/cli/commands/app/command.rb +2 -2
  12. data/lib/hanami/cli/commands/app/dev.rb +45 -0
  13. data/lib/hanami/cli/commands/app/generate/action.rb +3 -2
  14. data/lib/hanami/cli/commands/app/generate/part.rb +49 -0
  15. data/lib/hanami/cli/commands/app/install.rb +16 -1
  16. data/lib/hanami/cli/commands/app.rb +9 -0
  17. data/lib/hanami/cli/commands/gem/new.rb +57 -7
  18. data/lib/hanami/cli/errors.rb +30 -0
  19. data/lib/hanami/cli/files.rb +8 -2
  20. data/lib/hanami/cli/generators/app/action/action.erb +5 -1
  21. data/lib/hanami/cli/generators/app/action/slice_action.erb +5 -1
  22. data/lib/hanami/cli/generators/app/action.rb +49 -12
  23. data/lib/hanami/cli/generators/app/part/app_base_part.erb +9 -0
  24. data/lib/hanami/cli/generators/app/part/app_part.erb +13 -0
  25. data/lib/hanami/cli/generators/app/part/slice_base_part.erb +9 -0
  26. data/lib/hanami/cli/generators/app/part/slice_part.erb +13 -0
  27. data/lib/hanami/cli/generators/app/part.rb +101 -0
  28. data/lib/hanami/cli/generators/app/part_context.rb +98 -0
  29. data/lib/hanami/cli/generators/app/slice/app_css.erb +5 -0
  30. data/lib/hanami/cli/generators/app/slice/app_js.erb +1 -0
  31. data/lib/hanami/cli/generators/app/slice/app_layout.erb +18 -0
  32. data/lib/hanami/cli/generators/app/slice.rb +9 -3
  33. data/lib/hanami/cli/generators/app/slice_context.rb +18 -0
  34. data/lib/hanami/cli/generators/context.rb +70 -3
  35. data/lib/hanami/cli/generators/gem/app/404.html +76 -5
  36. data/lib/hanami/cli/generators/gem/app/500.html +76 -5
  37. data/lib/hanami/cli/generators/gem/app/app_css.erb +5 -0
  38. data/lib/hanami/cli/generators/gem/app/app_js.erb +1 -0
  39. data/lib/hanami/cli/generators/gem/app/app_layout.erb +18 -0
  40. data/lib/hanami/cli/generators/gem/app/assets.mjs +14 -0
  41. data/lib/hanami/cli/generators/gem/app/dev +8 -0
  42. data/lib/hanami/cli/generators/gem/app/favicon.ico +0 -0
  43. data/lib/hanami/cli/generators/gem/app/gemfile.erb +14 -8
  44. data/lib/hanami/cli/generators/gem/app/gitignore.erb +4 -0
  45. data/lib/hanami/cli/generators/gem/app/package.json.erb +10 -0
  46. data/lib/hanami/cli/generators/gem/app/procfile.erb +4 -0
  47. data/lib/hanami/cli/generators/gem/app/puma.erb +37 -7
  48. data/lib/hanami/cli/generators/gem/app/routes.erb +1 -1
  49. data/lib/hanami/cli/generators/gem/app.rb +21 -4
  50. data/lib/hanami/cli/generators/version.rb +12 -0
  51. data/lib/hanami/cli/interactive_system_call.rb +64 -0
  52. data/lib/hanami/cli/system_call.rb +8 -2
  53. data/lib/hanami/cli/version.rb +1 -1
  54. metadata +28 -6
  55. data/lib/hanami/cli/generators/app/slice/layouts_app.html.erb +0 -1
  56. data/lib/hanami/cli/generators/gem/app/layouts_app.html.erb +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '078a7a10f1196ed8635a9c27ee48ac10178cdcff50d2646138f61b55f79f86a7'
4
- data.tar.gz: 870c056fc5da9f5952daf357ca2861f0e276510c6ca1e63a2f821af76ebdd09a
3
+ metadata.gz: '054178514bf7e420e00cd8da8a148cd4d479609668c180507fadbcd7a086f15d'
4
+ data.tar.gz: 3ef8c388ad8c8734179ce042d3eb966dea6df881b72e7615f0b104a1890106a5
5
5
  SHA512:
6
- metadata.gz: d70ee9d87779f442c25517abfefde102460848e8a29ba9ef30ae28cc2b2593f73027dad42b99e5617820952a84fd22013a8de5d039fb2e6161a64fd2eef706a1
7
- data.tar.gz: 815418cd1c416bea1f7a77c56dff20ed143b582795bbcd79904260509c8c62c7d62a7be76c11305d26dc793dd2c2a13fcba0532c365ad47278212159e40eff69
6
+ metadata.gz: c8e1abc0ded22d56ee2acd5dec6d9f7079c0331d187b1d4ff4b26858faf50ff870016e1adfa6b785673d39b6d0dcf097dca7c1b0526da442e1939ce0952f3799
7
+ data.tar.gz: 8ecc3ceefc10856cbd2f60ec24bd1ecde442764610dbb7d179f064080ac434fa4829374efb05513c67420ab8b76b0280ad594fd566824fdfba0e8d14afc209fb
data/CHANGELOG.md CHANGED
@@ -2,6 +2,43 @@
2
2
 
3
3
  Hanami Command Line Interface
4
4
 
5
+ ## v2.1.0.rc1 - 2023-11-01
6
+
7
+ ### Added
8
+
9
+ - [Tim Riley] `hanami new` to generate `bin/dev` as configuration for `hanami dev`
10
+ - [Luca Guidi] Introducing `hanami generate part` to generate view parts
11
+
12
+ ### Fixed
13
+
14
+ - [Luca Guidi] `hanami new` generates a fully documented Puma configuration in `config/puma.rb`
15
+
16
+ ### Changed
17
+
18
+ - [Tim Riley] `hanami new` generates a `config/assets.mjs` as Assets configuration
19
+ - [Tim Riley] `hanami new` generates a leaner `package.json`
20
+ - [Tim Riley] `hanami new` doesn't generate a default root route anymore
21
+ - [Aaron Moodie & Tim Riley] `hanami new` to generate a redesigned 404 and 500 error pages
22
+ - [Luca Guidi] When generating a RESTful action, skip `create`, if `new` is present, and `update`, if `edit` is present
23
+
24
+ ## v2.1.0.beta2 - 2023-10-04
25
+
26
+ ### Added
27
+
28
+ - [Luca Guidi] `hanami new` generates `Procfile.dev`
29
+ - [Luca Guidi] `hanami new` generates basic app assets, if `hanami-assets` is bundled by the app
30
+ - [Luca Guidi] `hanami new` accepts `--head` to generate the app using Hanami HEAD version from GitHub
31
+ - [Luca Guidi] `hanami generate slice` generates basic slice assets, if `hanami-assets` is bundled by the app
32
+ - [Ryan Bigg] `hanami generate action` generates corresponding view, if `hanami-view` is bundled by the app
33
+ - [Luca Guidi] `hanami assets compile` to compile assets at the deploy time
34
+ - [Luca Guidi] `hanami assets watch` to watch and compile assets at the development time
35
+ - [Luca Guidi] `hanami dev` to start the processes in `Procfile.dev`
36
+
37
+ ### Fixed
38
+
39
+ - [Luca Guidi] `hanami new` generates a `Gemfile` with `hanami-webconsole` in `:development` group
40
+ - [Luca Guidi] `hanami new` generates a `Gemfile` with versioned `hanami-webconsole`, `hanami-rspec`, and `hanami-reloader`
41
+
5
42
  ## v2.1.0.beta1 - 2023-06-29
6
43
 
7
44
  ### Added
data/Gemfile CHANGED
@@ -10,9 +10,12 @@ unless ENV["CI"]
10
10
  end
11
11
 
12
12
  gem "hanami", github: "hanami/hanami", branch: "main"
13
- gem "hanami-utils", github: "hanami/utils", branch: "main"
14
- gem "hanami-router", github: "hanami/router", branch: "main"
13
+ gem "hanami-assets", github: "hanami/assets", branch: "main"
15
14
  gem "hanami-controller", github: "hanami/controller", branch: "main"
15
+ gem "hanami-router", github: "hanami/router", branch: "main"
16
+ gem "hanami-utils", github: "hanami/utils", branch: "main"
17
+
18
+ gem "dry-files", github: "dry-rb/dry-files", branch: "main"
16
19
 
17
20
  gem "rack"
18
21
 
data/hanami-cli.gemspec CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.add_dependency "bundler", "~> 2.1"
34
34
  spec.add_dependency "dry-cli", "~> 1.0", "< 2"
35
- spec.add_dependency "dry-files", "~> 1.0", ">= 1.0.1", "< 2"
35
+ spec.add_dependency "dry-files", "~> 1.0", ">= 1.0.2", "< 2"
36
36
  spec.add_dependency "dry-inflector", "~> 1.0", "< 2"
37
37
  spec.add_dependency "rake", "~> 13.0"
38
38
  spec.add_dependency "zeitwerk", "~> 2.6"
@@ -3,7 +3,7 @@
3
3
  require "bundler"
4
4
  require "open3"
5
5
  require "etc"
6
- require "dry/files"
6
+ require_relative "files"
7
7
  require_relative "system_call"
8
8
  require_relative "errors"
9
9
 
@@ -45,12 +45,12 @@ module Hanami
45
45
 
46
46
  # Returns a new bundler.
47
47
  #
48
- # @param fs [Dry::Files] the filesystem interaction object
48
+ # @param fs [Hanami::CLI::Files] the filesystem interaction object
49
49
  # @param system_call [SystemCall] convenience object for making system calls
50
50
  #
51
51
  # @since 2.0.0
52
52
  # @api public
53
- def initialize(fs: Dry::Files.new, system_call: SystemCall.new)
53
+ def initialize(fs: Hanami::CLI::Files.new, system_call: SystemCall.new)
54
54
  @fs = fs
55
55
  @system_call = system_call
56
56
  end
@@ -71,7 +71,7 @@ module Hanami
71
71
  #
72
72
  # @return [SystemCall::Result] the result of the `bundle` command execution
73
73
  #
74
- # @raise [StandardError] if the `bundle` command does not execute successfully
74
+ # @raise [Hanami::CLI::BundleInstallError] if the `bundle` command does not execute successfully
75
75
  #
76
76
  # @since 2.0.0
77
77
  # @api public
@@ -81,6 +81,20 @@ module Hanami
81
81
  end
82
82
  end
83
83
 
84
+ # Runs the given Hanami CLI command via `bundle exec hanami`
85
+ #
86
+ # @return [SystemCall::Result] the result of the command execution
87
+ #
88
+ # @raise [Hanami::CLI::HanamiExecError] if the does not execute successfully
89
+ #
90
+ # @since 2.1.0
91
+ # @api public
92
+ def hanami_exec(cmd, env: nil, &blk)
93
+ exec("hanami #{cmd}", env: env, &blk).tap do |result|
94
+ raise HanamiExecError.new(cmd, result.err) unless result.successful?
95
+ end
96
+ end
97
+
84
98
  # Executes the given command prefixed by `bundle exec`.
85
99
  #
86
100
  # @return [SystemCall::Result] the result of the command execution
@@ -127,7 +141,7 @@ module Hanami
127
141
 
128
142
  private
129
143
 
130
- # @return [Dry::Files]
144
+ # @return [Hanami::CLI::Files]
131
145
  #
132
146
  # @since 2.0.0
133
147
  # @api public
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "dry/cli"
4
- require "dry/files"
5
4
  require "dry/inflector"
5
+ require_relative "files"
6
6
 
7
7
  module Hanami
8
8
  module CLI
@@ -19,12 +19,12 @@ module Hanami
19
19
  #
20
20
  # @param out [IO] I/O stream for standard command output
21
21
  # @param err [IO] I/O stream for comment errror output
22
- # @param fs [Dry::Files] object for managing file system interactions
22
+ # @param fs [Hanami::CLI::Files] object for managing file system interactions
23
23
  # @param inflector [Dry::Inflector] inflector for any command-level inflections
24
24
  #
25
25
  # @since 2.0.0
26
26
  # @api public
27
- def initialize(out: $stdout, err: $stderr, fs: Dry::Files.new, inflector: Dry::Inflector.new)
27
+ def initialize(out: $stdout, err: $stderr, fs: Hanami::CLI::Files.new, inflector: Dry::Inflector.new)
28
28
  super()
29
29
  @out = out
30
30
  @err = err
@@ -52,7 +52,7 @@ module Hanami
52
52
 
53
53
  # Returns the object for managing file system interactions.
54
54
  #
55
- # @return [Dry::Files]
55
+ # @return [Hanami::CLI::Files]
56
56
  #
57
57
  # @since 2.0.0
58
58
  # @api public
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "shellwords"
4
+ require_relative "../command"
5
+ require_relative "../../../system_call"
6
+
7
+ module Hanami
8
+ module CLI
9
+ module Commands
10
+ module App
11
+ module Assets
12
+ # @since 2.1.0
13
+ # @api private
14
+ class Command < App::Command
15
+ def initialize(config: app.config.assets, system_call: SystemCall.new, **)
16
+ super()
17
+ @system_call = system_call
18
+ @config = config
19
+ end
20
+
21
+ # @since 2.1.0
22
+ # @api private
23
+ def call(**)
24
+ cmd, *args = cmd_with_args
25
+
26
+ system_call.call(cmd, *args)
27
+ end
28
+
29
+ private
30
+
31
+ # @since 2.1.0
32
+ # @api private
33
+ attr_reader :config
34
+
35
+ # @since 2.1.0
36
+ # @api private
37
+ attr_reader :system_call
38
+
39
+ # @since 2.1.0
40
+ # @api private
41
+ def cmd_with_args
42
+ [config.package_manager_run_command, "assets"]
43
+ end
44
+
45
+ # @since 2.1.0
46
+ # @api private
47
+ def entry_points
48
+ config.entry_points.map do |entry_point|
49
+ escape(entry_point)
50
+ end.join(" ")
51
+ end
52
+
53
+ # @since 2.1.0
54
+ # @api private
55
+ def destination
56
+ escape(config.destination)
57
+ end
58
+
59
+ # @since 2.1.0
60
+ # @api private
61
+ def escape(str)
62
+ Shellwords.shellescape(str)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "command"
4
+
5
+ module Hanami
6
+ module CLI
7
+ module Commands
8
+ module App
9
+ module Assets
10
+ # @since 2.1.0
11
+ # @api private
12
+ class Compile < Assets::Command
13
+ desc "Compile assets for deployments"
14
+
15
+ # @since 2.1.0
16
+ # @api private
17
+ def cmd_with_args
18
+ result = super
19
+
20
+ if config.subresource_integrity.any?
21
+ result << "--"
22
+ result << "--sri=#{config.subresource_integrity.join(',')}"
23
+ end
24
+
25
+ result
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "command"
4
+ require_relative "../../../interactive_system_call"
5
+
6
+ module Hanami
7
+ module CLI
8
+ module Commands
9
+ module App
10
+ module Assets
11
+ # @since 2.1.0
12
+ # @api private
13
+ class Watch < Assets::Command
14
+ desc "Start assets watch mode"
15
+
16
+ def initialize(config: app.config.assets, system_call: InteractiveSystemCall.new, **)
17
+ super(config: config, system_call: system_call)
18
+ end
19
+
20
+ private
21
+
22
+ # @since 2.1.0
23
+ # @api private
24
+ def cmd_with_args
25
+ super + ["--", "--watch"]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ module CLI
5
+ module Commands
6
+ module App
7
+ # @since 2.1.0
8
+ # @api private
9
+ module Assets
10
+ require_relative "assets/compile"
11
+ require_relative "assets/watch"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/files"
4
3
  require "hanami/env"
5
4
  require_relative "db/utils/database"
5
+ require_relative "../../files"
6
6
 
7
7
  module Hanami
8
8
  module CLI
@@ -75,7 +75,7 @@ module Hanami
75
75
  klass.new(
76
76
  out: out,
77
77
  inflector: app.inflector,
78
- fs: Dry::Files
78
+ fs: Hanami::CLI::Files,
79
79
  ).call(*args)
80
80
  end
81
81
 
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../interactive_system_call"
4
+
5
+ module Hanami
6
+ module CLI
7
+ module Commands
8
+ module App
9
+ # @since 2.1.0
10
+ # @api private
11
+ class Dev < App::Command
12
+ # @since 2.1.0
13
+ # @api private
14
+ desc "Start the application in development mode"
15
+
16
+ # @since 2.1.0
17
+ # @api private
18
+ def initialize(interactive_system_call: InteractiveSystemCall.new, **)
19
+ @interactive_system_call = interactive_system_call
20
+ super()
21
+ end
22
+
23
+ # @since 2.1.0
24
+ # @api private
25
+ def call(**)
26
+ bin, args = executable
27
+ interactive_system_call.call(bin, *args)
28
+ end
29
+
30
+ private
31
+
32
+ # @since 2.1.0
33
+ # @api private
34
+ attr_reader :interactive_system_call
35
+
36
+ # @since 2.1.0
37
+ # @api private
38
+ def executable
39
+ [::File.join("bin", "dev")]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -60,7 +60,8 @@ module Hanami
60
60
 
61
61
  # @since 2.0.0
62
62
  # @api private
63
- def call(name:, url: nil, http: nil, format: DEFAULT_FORMAT, skip_view: DEFAULT_SKIP_VIEW, slice: nil, **)
63
+ def call(name:, url: nil, http: nil, format: DEFAULT_FORMAT, skip_view: DEFAULT_SKIP_VIEW, slice: nil,
64
+ context: nil, **)
64
65
  slice = inflector.underscore(Shellwords.shellescape(slice)) if slice
65
66
  name = naming.action_name(name)
66
67
  *controller, action = name.split(ACTION_SEPARATOR)
@@ -69,7 +70,7 @@ module Hanami
69
70
  raise InvalidActionNameError.new(name)
70
71
  end
71
72
 
72
- generator.call(app.namespace, controller, action, url, http, format, skip_view, slice)
73
+ generator.call(app.namespace, controller, action, url, http, format, skip_view, slice, context: context)
73
74
  end
74
75
 
75
76
  # rubocop:enable Metrics/ParameterLists
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/inflector"
4
+ require "dry/files"
5
+ require "shellwords"
6
+
7
+ module Hanami
8
+ module CLI
9
+ module Commands
10
+ module App
11
+ module Generate
12
+ # @since 2.1.0
13
+ # @api private
14
+ class Part < App::Command
15
+ argument :name, required: true, desc: "Part name"
16
+ option :slice, required: false, desc: "Slice name"
17
+
18
+ example [
19
+ %(book (MyApp::Views::Parts::Book)),
20
+ %(book --slice=admin (Admin::Views::Parts::Book)),
21
+ ]
22
+ attr_reader :generator
23
+ private :generator
24
+
25
+ # @since 2.0.0
26
+ # @api private
27
+ def initialize(
28
+ fs: Hanami::CLI::Files.new,
29
+ inflector: Dry::Inflector.new,
30
+ generator: Generators::App::Part.new(fs: fs, inflector: inflector),
31
+ **
32
+ )
33
+ @generator = generator
34
+ super(fs: fs)
35
+ end
36
+
37
+ # @since 2.0.0
38
+ # @api private
39
+ def call(name:, slice: nil, **)
40
+ slice = inflector.underscore(Shellwords.shellescape(slice)) if slice
41
+
42
+ generator.call(app.namespace, name, slice)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../../system_call"
4
+
3
5
  module Hanami
4
6
  module CLI
5
7
  module Commands
@@ -18,9 +20,22 @@ module Hanami
18
20
  # @since 2.0.0
19
21
  # @api private
20
22
  class Install < Command
23
+ # @since 2.1.0
24
+ # @api private
25
+ DEFAULT_HEAD = false
26
+ private_constant :DEFAULT_HEAD
27
+
28
+ # @since 2.1.0
29
+ # @api private
21
30
  desc "Install Hanami third-party plugins"
22
31
 
23
- def call(*)
32
+ # @since 2.1.0
33
+ # @api private
34
+ option :head, type: :boolean, desc: "Install head deps", default: DEFAULT_HEAD
35
+
36
+ # @since 2.0.0
37
+ # @api private
38
+ def call(head: DEFAULT_HEAD, **)
24
39
  end
25
40
  end
26
41
  end
@@ -14,15 +14,24 @@ module Hanami
14
14
  base.module_eval do
15
15
  register "version", Commands::App::Version, aliases: ["v", "-v", "--version"]
16
16
  register "install", Commands::App::Install
17
+ register "dev", Commands::App::Dev
17
18
  register "console", Commands::App::Console, aliases: ["c"]
18
19
  register "server", Commands::App::Server, aliases: ["s"]
19
20
  register "routes", Commands::App::Routes
20
21
  register "middleware", Commands::App::Middleware
21
22
 
23
+ if Hanami.bundled?("hanami-assets")
24
+ register "assets" do |prefix|
25
+ prefix.register "compile", Assets::Compile
26
+ prefix.register "watch", Assets::Watch
27
+ end
28
+ end
29
+
22
30
  register "generate", aliases: ["g"] do |prefix|
23
31
  prefix.register "slice", Generate::Slice
24
32
  prefix.register "action", Generate::Action
25
33
  prefix.register "view", Generate::View
34
+ prefix.register "part", Generate::Part
26
35
  end
27
36
  end
28
37
  end
@@ -10,21 +10,55 @@ module Hanami
10
10
  # @since 2.0.0
11
11
  # @api private
12
12
  class New < Command
13
+ # @since 2.0.0
14
+ # @api private
13
15
  SKIP_INSTALL_DEFAULT = false
14
16
  private_constant :SKIP_INSTALL_DEFAULT
15
17
 
18
+ # @since 2.1.0
19
+ # @api private
20
+ HEAD_DEFAULT = false
21
+ private_constant :HEAD_DEFAULT
22
+
23
+ # @since 2.1.0
24
+ # @api private
25
+ SKIP_ASSETS_DEFAULT = false
26
+ private_constant :SKIP_ASSETS_DEFAULT
27
+
16
28
  desc "Generate a new Hanami app"
17
29
 
30
+ # @since 2.0.0
31
+ # @api private
18
32
  argument :app, required: true, desc: "App name"
19
33
 
34
+ # @since 2.0.0
35
+ # @api private
20
36
  option :skip_install, type: :boolean, required: false,
21
37
  default: SKIP_INSTALL_DEFAULT,
22
38
  desc: "Skip app installation (Bundler, third-party Hanami plugins)"
23
39
 
40
+ # @since 2.1.0
41
+ # @api private
42
+ option :head, type: :boolean, required: false,
43
+ default: HEAD_DEFAULT,
44
+ desc: "Use Hanami HEAD version (from GitHub `main` branches)"
45
+
46
+ # @since 2.1.0
47
+ # @api private
48
+ option :skip_assets, type: :boolean, required: false,
49
+ default: SKIP_ASSETS_DEFAULT,
50
+ desc: "Skip assets"
51
+
52
+ # rubocop:disable Layout/LineLength
24
53
  example [
25
- "bookshelf # Generate a new Hanami app in `bookshelf/' directory, using `Bookshelf' namespace", # rubocop:disable Layout/LineLength
26
- "bookshelf --skip-install # Generate a new Hanami app, but it skips Hanami installation"
54
+ "bookshelf # Generate a new Hanami app in `bookshelf/' directory, using `Bookshelf' namespace",
55
+ "bookshelf --head # Generate a new Hanami app, using Hanami HEAD version from GitHub `main' branches",
56
+ "bookshelf --skip-install # Generate a new Hanami app, but it skips Hanami installation",
57
+ "bookshelf --skip-assets # Generate a new Hanami app without assets"
27
58
  ]
59
+ # rubocop:enable Layout/LineLength
60
+
61
+ # rubocop:disable Metrics/ParameterLists
28
62
 
29
63
  # @since 2.0.0
30
64
  # @api private
@@ -33,42 +67,58 @@ module Hanami
33
67
  inflector: Dry::Inflector.new,
34
68
  bundler: CLI::Bundler.new(fs: fs),
35
69
  generator: Generators::Gem::App.new(fs: fs, inflector: inflector),
70
+ system_call: SystemCall.new,
36
71
  **other
37
72
  )
38
73
  @bundler = bundler
39
74
  @generator = generator
75
+ @system_call = system_call
40
76
  super(fs: fs, inflector: inflector, **other)
41
77
  end
42
78
 
79
+ # rubocop:enable Metrics/ParameterLists
80
+
81
+ # rubocop:disable Metrics/AbcSize
82
+
43
83
  # @since 2.0.0
44
84
  # @api private
45
- def call(app:, skip_install: SKIP_INSTALL_DEFAULT, **)
85
+ def call(app:, head: HEAD_DEFAULT, skip_install: SKIP_INSTALL_DEFAULT, skip_assets: SKIP_ASSETS_DEFAULT, **)
46
86
  app = inflector.underscore(app)
47
87
 
48
88
  raise PathAlreadyExistsError.new(app) if fs.exist?(app)
49
89
 
50
90
  fs.mkdir(app)
51
91
  fs.chdir(app) do
52
- generator.call(app) do
92
+ context = Generators::Context.new(inflector, app, head: head, skip_assets: skip_assets)
93
+ generator.call(app, context: context) do
53
94
  if skip_install
54
95
  out.puts "Skipping installation, please enter `#{app}' directory and run `bundle exec hanami install'"
55
96
  else
56
97
  out.puts "Running Bundler install..."
57
98
  bundler.install!
99
+
100
+ unless skip_assets
101
+ out.puts "Running npm install..."
102
+ system_call.call("npm", ["install"])
103
+ end
104
+
58
105
  out.puts "Running Hanami install..."
59
- run_install_commmand!
106
+ run_install_commmand!(head: head)
60
107
  end
61
108
  end
62
109
  end
63
110
  end
111
+ # rubocop:enable Metrics/AbcSize
64
112
 
65
113
  private
66
114
 
67
115
  attr_reader :bundler
68
116
  attr_reader :generator
117
+ attr_reader :system_call
69
118
 
70
- def run_install_commmand!
71
- bundler.exec("hanami install").tap do |result|
119
+ def run_install_commmand!(head:)
120
+ head_flag = head ? " --head" : ""
121
+ bundler.exec("hanami install#{head_flag}").tap do |result|
72
122
  raise HanamiInstallError.new(result.err) unless result.successful?
73
123
  end
74
124
  end