hanami-cli 2.0.3 → 2.1.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/Gemfile +3 -2
  4. data/LICENSE.md +1 -1
  5. data/README.md +1 -1
  6. data/hanami-cli.gemspec +1 -1
  7. data/lib/hanami/cli/bundler.rb +21 -7
  8. data/lib/hanami/cli/command.rb +4 -4
  9. data/lib/hanami/cli/commands/app/assets/command.rb +82 -0
  10. data/lib/hanami/cli/commands/app/assets/compile.rb +32 -0
  11. data/lib/hanami/cli/commands/app/assets/watch.rb +36 -0
  12. data/lib/hanami/cli/commands/app/assets.rb +16 -0
  13. data/lib/hanami/cli/commands/app/command.rb +2 -2
  14. data/lib/hanami/cli/commands/app/db/rollback.rb +30 -6
  15. data/lib/hanami/cli/commands/app/db/utils/database.rb +5 -1
  16. data/lib/hanami/cli/commands/app/dev.rb +57 -0
  17. data/lib/hanami/cli/commands/app/generate/action.rb +5 -4
  18. data/lib/hanami/cli/commands/app/generate/view.rb +57 -0
  19. data/lib/hanami/cli/commands/app/generate.rb +2 -2
  20. data/lib/hanami/cli/commands/app/install.rb +44 -1
  21. data/lib/hanami/cli/commands/app.rb +9 -0
  22. data/lib/hanami/cli/commands/gem/new.rb +41 -7
  23. data/lib/hanami/cli/errors.rb +30 -0
  24. data/lib/hanami/cli/files.rb +8 -2
  25. data/lib/hanami/cli/generators/app/action/action.erb +5 -1
  26. data/lib/hanami/cli/generators/app/action/slice_action.erb +5 -1
  27. data/lib/hanami/cli/generators/app/action/slice_template.html.erb +1 -0
  28. data/lib/hanami/cli/generators/app/action/slice_view.erb +10 -0
  29. data/lib/hanami/cli/generators/app/action/template.html.erb +1 -2
  30. data/lib/hanami/cli/generators/app/action/view.erb +2 -5
  31. data/lib/hanami/cli/generators/app/action.rb +34 -22
  32. data/lib/hanami/cli/generators/app/action_context.rb +1 -1
  33. data/lib/hanami/cli/generators/app/slice/app_css.erb +5 -0
  34. data/lib/hanami/cli/generators/app/slice/app_js.erb +1 -0
  35. data/lib/hanami/cli/generators/app/slice/app_layout.erb +18 -0
  36. data/lib/hanami/cli/generators/app/slice/helpers.erb +10 -0
  37. data/lib/hanami/cli/generators/app/slice/view.erb +0 -2
  38. data/lib/hanami/cli/generators/app/slice.rb +15 -6
  39. data/lib/hanami/cli/generators/app/slice_context.rb +18 -0
  40. data/lib/hanami/cli/generators/app/view/app_template.html.erb +1 -0
  41. data/lib/hanami/cli/generators/app/view/app_view.erb +10 -0
  42. data/lib/hanami/cli/generators/app/view/slice_template.html.erb +1 -0
  43. data/lib/hanami/cli/generators/app/view/slice_view.erb +10 -0
  44. data/lib/hanami/cli/generators/app/view.rb +89 -0
  45. data/lib/hanami/cli/generators/app/view_context.rb +100 -0
  46. data/lib/hanami/cli/generators/context.rb +53 -4
  47. data/lib/hanami/cli/generators/gem/app/404.html +11 -0
  48. data/lib/hanami/cli/generators/gem/app/500.html +11 -0
  49. data/lib/hanami/cli/generators/gem/app/app_css.erb +5 -0
  50. data/lib/hanami/cli/generators/gem/app/app_js.erb +1 -0
  51. data/lib/hanami/cli/generators/gem/app/app_layout.erb +18 -0
  52. data/lib/hanami/cli/generators/gem/app/favicon.ico +0 -0
  53. data/lib/hanami/cli/generators/gem/app/gemfile.erb +14 -6
  54. data/lib/hanami/cli/generators/gem/app/gitignore.erb +4 -0
  55. data/lib/hanami/cli/generators/gem/app/helpers.erb +10 -0
  56. data/lib/hanami/cli/generators/gem/app/procfile.erb +4 -0
  57. data/lib/hanami/cli/generators/gem/app/puma.erb +5 -3
  58. data/lib/hanami/cli/generators/gem/app/view.erb +9 -0
  59. data/lib/hanami/cli/generators/gem/app.rb +15 -1
  60. data/lib/hanami/cli/interactive_system_call.rb +64 -0
  61. data/lib/hanami/cli/system_call.rb +8 -2
  62. data/lib/hanami/cli/url.rb +1 -1
  63. data/lib/hanami/cli/version.rb +1 -1
  64. metadata +35 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4bcebd7bee28802b90462073bbc9def8c6f1c13b7fc032cc8f20859b082310a4
4
- data.tar.gz: fd38025e1fa7a2b5c6650710e16076fefa8f8697a1b3bba3035eedaa9ce612b4
3
+ metadata.gz: 85a528645e9205c15ccdf4b81cc32a3fb0789a8a7f07c56554c1b8b0e66b9e91
4
+ data.tar.gz: 5937fd333d11a7f5131d0298dc609c8a92e233249bc0b2e9e8f28705977f20b4
5
5
  SHA512:
6
- metadata.gz: bdebf6ac07bfad66d9a7d37050ce6b91c7d29abc781c44807a0efdc8c7085db42ed7afcbf5b5b32f264213499e59d31754823a670eb43d71acee1be39dd0b5c2
7
- data.tar.gz: 56a41e42c83896516b0b20d7aea8864743c9a96508fd520d226de683d59de612a85cd99e83f7ed50bf39cfa87564152afb903bbfdc6d4d8e48ed9eb1904705e1
6
+ metadata.gz: df19a905d03fec4665ce80dd89730dee6337312e32e0e923e9424a387d66b8f9605e8392a5a73bd4627251b96c57b4a95f4df32062d8a53d42041d69841c10d6
7
+ data.tar.gz: e4931266c0517de1bb33bc0f862c73da58366d6d5707c0eacf48fd38b08b8d7ae767e8fd7c81f1f048b96ffda5977674e556e281c51ab1f2a4eb30c6ceaa7ade
data/CHANGELOG.md CHANGED
@@ -2,6 +2,39 @@
2
2
 
3
3
  Hanami Command Line Interface
4
4
 
5
+ ## v2.1.0.beta2 - 2023-10-04
6
+
7
+ ### Added
8
+
9
+ - [Luca Guidi] `hanami new` generates `Procfile.dev`
10
+ - [Luca Guidi] `hanami new` generates basic app assets, if `hanami-assets` is bundled by the app
11
+ - [Luca Guidi] `hanami new` accepts `--head` to generate the app using Hanami HEAD version from GitHub
12
+ - [Luca Guidi] `hanami generate slice` generates basic slice assets, if `hanami-assets` is bundled by the app
13
+ - [Ryan Bigg] `hanami generate action` generates corresponding view, if `hanami-view` is bundled by the app
14
+ - [Luca Guidi] `hanami assets compile` to compile assets at the deploy time
15
+ - [Luca Guidi] `hanami assets watch` to watch and compile assets at the development time
16
+ - [Luca Guidi] `hanami dev` to start the processes in `Procfile.dev`
17
+
18
+ ### Fixed
19
+
20
+ - [Luca Guidi] `hanami new` generates a `Gemfile` with `hanami-webconsole` in `:development` group
21
+ - [Luca Guidi] `hanami new` generates a `Gemfile` with versioned `hanami-webconsole`, `hanami-rspec`, and `hanami-reloader`
22
+
23
+ ## v2.1.0.beta1 - 2023-06-29
24
+
25
+ ### Added
26
+
27
+ - [Tim Riley] `hanami new` to generate default views, templates, and helpers
28
+ - [Tim Riley] `hanami generate slice` to generate default views, templates, and helpers
29
+ - [Tim Riley] `hanami generate action` to generate associated view and template
30
+ - [Tim Riley] Introduced `hanami generate view`
31
+ - [Tim Riley] `hanami new` to generate `Gemfile` with `hanami-view` and `hanami-webconsole` gems
32
+ - [Tim Riley] `hanami new` to generate default error pages for `404` and `500` HTTP errors
33
+
34
+ ### Fixed
35
+
36
+ - [Philip Arndt] `hanami server` to start only one Puma worker by default
37
+
5
38
  ## v2.0.3 - 2023-02-01
6
39
 
7
40
  ### Added
data/Gemfile CHANGED
@@ -10,9 +10,10 @@ 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"
16
17
 
17
18
  gem "rack"
18
19
 
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright © 2014-2022 Luca Guidi
1
+ Copyright © 2014 Hanami Team
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -44,4 +44,4 @@ Everyone interacting in the `Hanami::CLI` project's codebases, issue trackers, c
44
44
 
45
45
  ## Copyright
46
46
 
47
- Copyright © 2014-2022 Hanami Team – Released under MIT License
47
+ Copyright © 2014 Hanami Team – Released under MIT License
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,9 +3,9 @@
3
3
  require "bundler"
4
4
  require "open3"
5
5
  require "etc"
6
- require "dry/files"
7
- require_relative "./system_call"
8
- require_relative "./errors"
6
+ require_relative "files"
7
+ require_relative "system_call"
8
+ require_relative "errors"
9
9
 
10
10
  module Hanami
11
11
  module CLI
@@ -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,82 @@
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, env: env)
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
+ [
43
+ config.package_manager_executable,
44
+ config.package_manager_command,
45
+ config.executable
46
+ ]
47
+ end
48
+
49
+ # @since 2.1.0
50
+ # @api private
51
+ def env
52
+ ENV.to_h.merge(
53
+ "ESBUILD_ENTRY_POINTS" => entry_points,
54
+ "ESBUILD_OUTDIR" => destination
55
+ )
56
+ end
57
+
58
+ # @since 2.1.0
59
+ # @api private
60
+ def entry_points
61
+ config.entry_points.map do |entry_point|
62
+ escape(entry_point)
63
+ end.join(" ")
64
+ end
65
+
66
+ # @since 2.1.0
67
+ # @api private
68
+ def destination
69
+ escape(config.destination)
70
+ end
71
+
72
+ # @since 2.1.0
73
+ # @api private
74
+ def escape(str)
75
+ Shellwords.shellescape(str)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ 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,36 @@
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 +
26
+ [
27
+ "--",
28
+ "--watch"
29
+ ]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ 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
 
@@ -20,12 +20,20 @@ module Hanami
20
20
  migration_code, migration_name = find_migration(target)
21
21
 
22
22
  if migration_name.nil?
23
- out.puts "==> migration file for target #{target} was not found"
23
+ output = if target
24
+ "==> migration file for target #{target} was not found"
25
+ else
26
+ "==> no migrations to rollback"
27
+ end
28
+
29
+ out.puts output
24
30
  return
25
31
  end
26
32
 
27
33
  measure "database #{database.name} rolled back to #{migration_name}" do
28
34
  database.run_migrations(target: Integer(migration_code))
35
+
36
+ true
29
37
  end
30
38
 
31
39
  run_command Structure::Dump if dump
@@ -33,14 +41,30 @@ module Hanami
33
41
 
34
42
  private
35
43
 
36
- def find_migration(code)
37
- migration = database.applied_migrations.then { |migrations|
44
+ def find_migration(code) # rubocop:disable Metrics/PerceivedComplexity
45
+ applied_migrations = database.applied_migrations
46
+
47
+ return if applied_migrations.empty?
48
+
49
+ # Rollback to initial state if we have only one migration and
50
+ # no target is specified. In this case the rollback target
51
+ # will be the current migration timestamp minus 1
52
+ if applied_migrations.one? && code.nil?
53
+ migration = applied_migrations.first
54
+
55
+ migration_code = Integer(migration.split("_").first) - 1
56
+ migration_name = "initial state"
57
+
58
+ return [migration_code, migration_name]
59
+ end
60
+
61
+ # Otherwise rollback to target or to previous migration
62
+ migration =
38
63
  if code
39
- migrations.detect { |m| m.split("_").first == code }
64
+ applied_migrations.detect { |m| m.split("_").first == code }
40
65
  else
41
- migrations.last
66
+ applied_migrations[-2]
42
67
  end
43
- }
44
68
 
45
69
  return unless migration
46
70
 
@@ -139,7 +139,11 @@ module Hanami
139
139
  @sequel_migrator ||= begin
140
140
  require "sequel"
141
141
  Sequel.extension :migration
142
- Sequel::TimestampMigrator.new(migrator.connection, migrations_path, {})
142
+
143
+ require "rom/sql"
144
+ ROM::SQL.with_gateway(gateway) do
145
+ Sequel::TimestampMigrator.new(migrator.connection, migrations_path, {})
146
+ end
143
147
  end
144
148
  end
145
149
 
@@ -0,0 +1,57 @@
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
+ option :procfile, type: :string, desc: "Path to Procfile", aliases: ["-f"]
19
+
20
+ # @since 2.1.0
21
+ # @api private
22
+ example [
23
+ "-f /path/to/Procfile",
24
+ ]
25
+
26
+ # @since 2.1.0
27
+ # @api private
28
+ def initialize(interactive_system_call: InteractiveSystemCall.new, **)
29
+ @interactive_system_call = interactive_system_call
30
+ super()
31
+ end
32
+
33
+ # @since 2.1.0
34
+ # @api private
35
+ def call(procfile: nil, **)
36
+ bin, args = executable(procfile: procfile)
37
+ interactive_system_call.call(bin, *args)
38
+ end
39
+
40
+ private
41
+
42
+ # @since 2.1.0
43
+ # @api private
44
+ attr_reader :interactive_system_call
45
+
46
+ # @since 2.1.0
47
+ # @api private
48
+ def executable(procfile: nil)
49
+ # TODO: support other implementations of Foreman
50
+ # See: https://github.com/ddollar/foreman#ports
51
+ ["foreman", ["start", "-f", procfile || "Procfile.dev"]]
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -26,8 +26,8 @@ module Hanami
26
26
  option :url, required: false, type: :string, desc: "Action URL"
27
27
  option :http, required: false, type: :string, desc: "Action HTTP method"
28
28
  # option :format, required: false, type: :string, default: DEFAULT_FORMAT, desc: "Template format"
29
- # option :skip_view, required: false, type: :boolean, default: DEFAULT_SKIP_VIEW,
30
- # desc: "Skip view and template generation"
29
+ option :skip_view, required: false, type: :boolean, default: DEFAULT_SKIP_VIEW,
30
+ desc: "Skip view and template generation"
31
31
  option :slice, required: false, desc: "Slice name"
32
32
 
33
33
  # rubocop:disable Layout/LineLength
@@ -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,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/inflector"
4
+ require "dry/files"
5
+ require "shellwords"
6
+ require_relative "../../../naming"
7
+ require_relative "../../../errors"
8
+
9
+ module Hanami
10
+ module CLI
11
+ module Commands
12
+ module App
13
+ module Generate
14
+ # @since 2.0.0
15
+ # @api private
16
+ class View < App::Command
17
+ # TODO: make this configurable
18
+ DEFAULT_FORMAT = "html"
19
+ private_constant :DEFAULT_FORMAT
20
+
21
+ # TODO: make engine configurable
22
+
23
+ argument :name, required: true, desc: "View name"
24
+ option :slice, required: false, desc: "Slice name"
25
+
26
+ example [
27
+ %(books.index (MyApp::Actions::Books::Index)),
28
+ %(books.index --slice=admin (Admin::Actions::Books::Index)),
29
+ ]
30
+ attr_reader :generator
31
+ private :generator
32
+
33
+ # @since 2.0.0
34
+ # @api private
35
+ def initialize(
36
+ fs: Hanami::CLI::Files.new,
37
+ inflector: Dry::Inflector.new,
38
+ generator: Generators::App::View.new(fs: fs, inflector: inflector),
39
+ **
40
+ )
41
+ @generator = generator
42
+ super(fs: fs)
43
+ end
44
+
45
+ # @since 2.0.0
46
+ # @api private
47
+ def call(name:, format: DEFAULT_FORMAT, slice: nil, **)
48
+ slice = inflector.underscore(Shellwords.shellescape(slice)) if slice
49
+
50
+ generator.call(app.namespace, name, format, slice)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -7,8 +7,8 @@ module Hanami
7
7
  # @since 2.0.0
8
8
  # @api private
9
9
  module Generate
10
- require_relative "./generate/slice"
11
- require_relative "./generate/action"
10
+ require_relative "generate/slice"
11
+ require_relative "generate/action"
12
12
  end
13
13
  end
14
14
  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,50 @@ 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.1.0
37
+ # @api private
38
+ def initialize(system_call: SystemCall.new, **)
39
+ @system_call = system_call
40
+ super()
41
+ end
42
+
43
+ # @since 2.0.0
44
+ # @api private
45
+ def call(head: DEFAULT_HEAD, **)
46
+ install_hanami_assets!(head: head)
47
+ end
48
+
49
+ private
50
+
51
+ # @since 2.1.0
52
+ # @api private
53
+ attr_reader :system_call
54
+
55
+ # @since 2.1.0
56
+ # @api private
57
+ def install_hanami_assets!(head:)
58
+ return unless Hanami.bundled?("hanami-assets")
59
+
60
+ system_call.call("npm", ["init", "-y"])
61
+
62
+ if head
63
+ system_call.call("npm", %w[install https://github.com/hanami/assets-js])
64
+ else
65
+ system_call.call("npm", %w[install hanami-assets])
66
+ end
24
67
  end
25
68
  end
26
69
  end