hanami-cli 2.1.0.beta1 → 2.1.0.beta2

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/Gemfile +3 -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 +82 -0
  8. data/lib/hanami/cli/commands/app/assets/compile.rb +32 -0
  9. data/lib/hanami/cli/commands/app/assets/watch.rb +36 -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 +57 -0
  13. data/lib/hanami/cli/commands/app/generate/action.rb +3 -2
  14. data/lib/hanami/cli/commands/app/install.rb +44 -1
  15. data/lib/hanami/cli/commands/app.rb +8 -0
  16. data/lib/hanami/cli/commands/gem/new.rb +41 -7
  17. data/lib/hanami/cli/errors.rb +30 -0
  18. data/lib/hanami/cli/files.rb +8 -2
  19. data/lib/hanami/cli/generators/app/action/action.erb +5 -1
  20. data/lib/hanami/cli/generators/app/action/slice_action.erb +5 -1
  21. data/lib/hanami/cli/generators/app/action.rb +3 -6
  22. data/lib/hanami/cli/generators/app/slice/app_css.erb +5 -0
  23. data/lib/hanami/cli/generators/app/slice/app_js.erb +1 -0
  24. data/lib/hanami/cli/generators/app/slice/app_layout.erb +18 -0
  25. data/lib/hanami/cli/generators/app/slice.rb +9 -3
  26. data/lib/hanami/cli/generators/app/slice_context.rb +18 -0
  27. data/lib/hanami/cli/generators/context.rb +52 -3
  28. data/lib/hanami/cli/generators/gem/app/app_css.erb +5 -0
  29. data/lib/hanami/cli/generators/gem/app/app_js.erb +1 -0
  30. data/lib/hanami/cli/generators/gem/app/app_layout.erb +18 -0
  31. data/lib/hanami/cli/generators/gem/app/favicon.ico +0 -0
  32. data/lib/hanami/cli/generators/gem/app/gemfile.erb +14 -8
  33. data/lib/hanami/cli/generators/gem/app/gitignore.erb +4 -0
  34. data/lib/hanami/cli/generators/gem/app/procfile.erb +4 -0
  35. data/lib/hanami/cli/generators/gem/app.rb +10 -2
  36. data/lib/hanami/cli/interactive_system_call.rb +64 -0
  37. data/lib/hanami/cli/system_call.rb +8 -2
  38. data/lib/hanami/cli/version.rb +1 -1
  39. metadata +18 -6
  40. data/lib/hanami/cli/generators/app/slice/layouts_app.html.erb +0 -1
  41. 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: 85a528645e9205c15ccdf4b81cc32a3fb0789a8a7f07c56554c1b8b0e66b9e91
4
+ data.tar.gz: 5937fd333d11a7f5131d0298dc609c8a92e233249bc0b2e9e8f28705977f20b4
5
5
  SHA512:
6
- metadata.gz: d70ee9d87779f442c25517abfefde102460848e8a29ba9ef30ae28cc2b2593f73027dad42b99e5617820952a84fd22013a8de5d039fb2e6161a64fd2eef706a1
7
- data.tar.gz: 815418cd1c416bea1f7a77c56dff20ed143b582795bbcd79904260509c8c62c7d62a7be76c11305d26dc793dd2c2a13fcba0532c365ad47278212159e40eff69
6
+ metadata.gz: df19a905d03fec4665ce80dd89730dee6337312e32e0e923e9424a387d66b8f9605e8392a5a73bd4627251b96c57b4a95f4df32062d8a53d42041d69841c10d6
7
+ data.tar.gz: e4931266c0517de1bb33bc0f862c73da58366d6d5707c0eacf48fd38b08b8d7ae767e8fd7c81f1f048b96ffda5977674e556e281c51ab1f2a4eb30c6ceaa7ade
data/CHANGELOG.md CHANGED
@@ -2,6 +2,24 @@
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
+
5
23
  ## v2.1.0.beta1 - 2023-06-29
6
24
 
7
25
  ### 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/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,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
 
@@ -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
@@ -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
@@ -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
@@ -14,11 +14,19 @@ 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
@@ -10,21 +10,53 @@ 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
28
60
 
29
61
  # @since 2.0.0
30
62
  # @api private
@@ -42,21 +74,22 @@ module Hanami
42
74
 
43
75
  # @since 2.0.0
44
76
  # @api private
45
- def call(app:, skip_install: SKIP_INSTALL_DEFAULT, **)
77
+ def call(app:, head: HEAD_DEFAULT, skip_install: SKIP_INSTALL_DEFAULT, skip_assets: SKIP_ASSETS_DEFAULT, **)
46
78
  app = inflector.underscore(app)
47
79
 
48
80
  raise PathAlreadyExistsError.new(app) if fs.exist?(app)
49
81
 
50
82
  fs.mkdir(app)
51
83
  fs.chdir(app) do
52
- generator.call(app) do
84
+ context = Generators::Context.new(inflector, app, head: head, skip_assets: skip_assets)
85
+ generator.call(app, context: context) do
53
86
  if skip_install
54
87
  out.puts "Skipping installation, please enter `#{app}' directory and run `bundle exec hanami install'"
55
88
  else
56
89
  out.puts "Running Bundler install..."
57
90
  bundler.install!
58
91
  out.puts "Running Hanami install..."
59
- run_install_commmand!
92
+ run_install_commmand!(head: head)
60
93
  end
61
94
  end
62
95
  end
@@ -67,8 +100,9 @@ module Hanami
67
100
  attr_reader :bundler
68
101
  attr_reader :generator
69
102
 
70
- def run_install_commmand!
71
- bundler.exec("hanami install").tap do |result|
103
+ def run_install_commmand!(head:)
104
+ head_flag = head ? " --head" : ""
105
+ bundler.exec("hanami install#{head_flag}").tap do |result|
72
106
  raise HanamiInstallError.new(result.err) unless result.successful?
73
107
  end
74
108
  end
@@ -2,60 +2,90 @@
2
2
 
3
3
  module Hanami
4
4
  module CLI
5
+ # @since 0.1.0
6
+ # @api public
5
7
  class Error < StandardError
6
8
  end
7
9
 
10
+ # @since 2.0.0
11
+ # @api public
8
12
  class NotImplementedError < Error
9
13
  end
10
14
 
15
+ # @since 2.0.0
16
+ # @api public
11
17
  class BundleInstallError < Error
12
18
  def initialize(message)
13
19
  super("`bundle install' failed\n\n\n#{message.inspect}")
14
20
  end
15
21
  end
16
22
 
23
+ # @since 2.0.0
24
+ # @api public
17
25
  class HanamiInstallError < Error
18
26
  def initialize(message)
19
27
  super("`hanami install' failed\n\n\n#{message.inspect}")
20
28
  end
21
29
  end
22
30
 
31
+ # @since 2.1.0
32
+ # @api public
33
+ class HanamiExecError < Error
34
+ def initialize(cmd, message)
35
+ super("`bundle exec hanami #{cmd}' failed\n\n\n#{message.inspect}")
36
+ end
37
+ end
38
+
39
+ # @since 2.0.0
40
+ # @api public
23
41
  class PathAlreadyExistsError < Error
24
42
  def initialize(path)
25
43
  super("Cannot create new Hanami app in an existing path: `#{path}'")
26
44
  end
27
45
  end
28
46
 
47
+ # @since 2.0.0
48
+ # @api public
29
49
  class MissingSliceError < Error
30
50
  def initialize(slice)
31
51
  super("slice `#{slice}' is missing, please generate with `hanami generate slice #{slice}'")
32
52
  end
33
53
  end
34
54
 
55
+ # @since 2.0.0
56
+ # @api public
35
57
  class InvalidURLError < Error
36
58
  def initialize(url)
37
59
  super("invalid URL: `#{url}'")
38
60
  end
39
61
  end
40
62
 
63
+ # @since 2.0.0
64
+ # @api public
41
65
  class InvalidURLPrefixError < Error
42
66
  def initialize(url)
43
67
  super("invalid URL prefix: `#{url}'")
44
68
  end
45
69
  end
46
70
 
71
+ # @since 2.0.0
72
+ # @api public
47
73
  class InvalidActionNameError < Error
48
74
  def initialize(name)
49
75
  super("cannot parse controller and action name: `#{name}'\n\texample: `hanami generate action users.show'")
50
76
  end
51
77
  end
52
78
 
79
+ # @since 2.0.0
80
+ # @api public
53
81
  class UnknownHTTPMethodError < Error
54
82
  def initialize(name)
55
83
  super("unknown HTTP method: `#{name}'")
56
84
  end
57
85
  end
58
86
 
87
+ # @since 2.0.0
88
+ # @api public
59
89
  class UnsupportedDatabaseSchemeError < Error
60
90
  def initialize(scheme)
61
91
  super("`#{scheme}' is not a supported db scheme")
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "dry/files"
4
+
3
5
  module Hanami
4
6
  module CLI
5
7
  # @since 2.0.0
@@ -29,7 +31,7 @@ module Hanami
29
31
  def mkdir(path)
30
32
  unless exist?(path)
31
33
  super
32
- created("#{path}/")
34
+ created(_path(path))
33
35
  end
34
36
  end
35
37
 
@@ -53,7 +55,11 @@ module Hanami
53
55
  end
54
56
 
55
57
  def within_folder(path)
56
- out.puts "-> Within #{path}/"
58
+ out.puts "-> Within #{_path(path)}"
59
+ end
60
+
61
+ def _path(path)
62
+ path + ::File::SEPARATOR
57
63
  end
58
64
  end
59
65
  end
@@ -4,8 +4,12 @@ module <%= camelized_app_name %>
4
4
  module Actions
5
5
  <%= module_controller_declaration %>
6
6
  <%= module_controller_offset %>class <%= camelized_action_name %> < <%= camelized_app_name %>::Action
7
- <%= module_controller_offset %> def handle(*, response)
7
+ <%- if bundled_views? -%>
8
+ <%= module_controller_offset %> def handle(request, response)
9
+ <%- else -%>
10
+ <%= module_controller_offset %> def handle(request, response)
8
11
  <%= module_controller_offset %> response.body = self.class.name
12
+ <%- end -%>
9
13
  <%= module_controller_offset %> end
10
14
  <%= module_controller_offset %>end
11
15
  <%= module_controller_end %>
@@ -4,8 +4,12 @@ module <%= camelized_slice_name %>
4
4
  module Actions
5
5
  <%= module_controller_declaration %>
6
6
  <%= module_controller_offset %>class <%= camelized_action_name %> < <%= camelized_slice_name %>::Action
7
- <%= module_controller_offset %> def handle(*, response)
7
+ <%- if bundled_views? -%>
8
+ <%= module_controller_offset %> def handle(request, response)
9
+ <%- else -%>
10
+ <%= module_controller_offset %> def handle(request, response)
8
11
  <%= module_controller_offset %> response.body = self.class.name
12
+ <%- end -%>
9
13
  <%= module_controller_offset %> end
10
14
  <%= module_controller_offset %>end
11
15
  <%= module_controller_end %>
@@ -19,11 +19,10 @@ module Hanami
19
19
  @inflector = inflector
20
20
  end
21
21
 
22
- # rubocop:disable Layout/LineLength
23
-
24
22
  # @since 2.0.0
25
23
  # @api private
26
- def call(app, controller, action, url, http, format, skip_view, slice, context: ActionContext.new(inflector, app, slice, controller, action))
24
+ def call(app, controller, action, url, http, format, skip_view, slice, context: nil)
25
+ context ||= ActionContext.new(inflector, app, slice, controller, action)
27
26
  if slice
28
27
  generate_for_slice(controller, action, url, http, format, skip_view, slice, context)
29
28
  else
@@ -31,8 +30,6 @@ module Hanami
31
30
  end
32
31
  end
33
32
 
34
- # rubocop:enable Layout/LineLength
35
-
36
33
  private
37
34
 
38
35
  ROUTE_HTTP_METHODS = %w[get post delete put patch trace options link unlink].freeze
@@ -136,7 +133,7 @@ module Hanami
136
133
  require "erb"
137
134
 
138
135
  ERB.new(
139
- File.read(__dir__ + "/action/#{path}")
136
+ File.read(__dir__ + "/action/#{path}"), trim_mode: "-",
140
137
  ).result(context.ctx)
141
138
  end
142
139
 
@@ -0,0 +1,5 @@
1
+ body {
2
+ background-color: #fff;
3
+ color: #000;
4
+ font-family: sans-serif;
5
+ }
@@ -0,0 +1 @@
1
+ import "../css/app.css";
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title><%= humanized_app_name %> - <%= humanized_slice_name %></title>
7
+ <%- if bundled_assets? -%>
8
+ <%%= favicon %>
9
+ <%= stylesheet_erb_tag %>
10
+ <%- end -%>
11
+ </head>
12
+ <body>
13
+ <%%= yield %>
14
+ <%- if bundled_assets? -%>
15
+ <%= javascript_erb_tag %>
16
+ <%- end -%>
17
+ </body>
18
+ </html>
@@ -30,8 +30,13 @@ module Hanami
30
30
  fs.write(fs.join(directory, "action.rb"), t("action.erb", context))
31
31
  fs.write(fs.join(directory, "view.rb"), t("view.erb", context))
32
32
  fs.write(fs.join(directory, "views", "helpers.rb"), t("helpers.erb", context))
33
- fs.write(fs.join(directory, "templates", "layouts", "app.html.erb"),
34
- File.read(File.join(__dir__, "slice", "layouts_app.html.erb")))
33
+ fs.write(fs.join(directory, "templates", "layouts", "app.html.erb"), t("app_layout.erb", context))
34
+
35
+ if context.bundled_assets?
36
+ fs.write(fs.join(directory, "assets", "js", "app.js"), t("app_js.erb", context))
37
+ fs.write(fs.join(directory, "assets", "css", "app.css"), t("app_css.erb", context))
38
+ end
39
+
35
40
  # fs.write(fs.join(directory, "/entities.rb"), t("entities.erb", context))
36
41
  # fs.write(fs.join(directory, "/repository.rb"), t("repository.erb", context))
37
42
 
@@ -53,7 +58,8 @@ module Hanami
53
58
  require "erb"
54
59
 
55
60
  ERB.new(
56
- File.read(__dir__ + "/slice/#{path}")
61
+ File.read(__dir__ + "/slice/#{path}"),
62
+ trim_mode: "-"
57
63
  ).result(context.ctx)
58
64
  end
59
65
 
@@ -29,6 +29,24 @@ module Hanami
29
29
  inflector.underscore(slice)
30
30
  end
31
31
 
32
+ # @since 2.1.0
33
+ # @api private
34
+ def humanized_slice_name
35
+ inflector.humanize(slice)
36
+ end
37
+
38
+ # @since 2.1.0
39
+ # @api private
40
+ def stylesheet_erb_tag
41
+ %(<%= css "#{slice}/app" %>)
42
+ end
43
+
44
+ # @since 2.1.0
45
+ # @api private
46
+ def javascript_erb_tag
47
+ %(<%= js "#{slice}/app" %>)
48
+ end
49
+
32
50
  private
33
51
 
34
52
  attr_reader :slice
@@ -12,9 +12,10 @@ module Hanami
12
12
  class Context
13
13
  # @since 2.0.0
14
14
  # @api private
15
- def initialize(inflector, app)
15
+ def initialize(inflector, app, **options)
16
16
  @inflector = inflector
17
17
  @app = app
18
+ @options = options
18
19
  end
19
20
 
20
21
  # @since 2.0.0
@@ -23,10 +24,20 @@ module Hanami
23
24
  binding
24
25
  end
25
26
 
27
+ def hanami_gem(name)
28
+ gem_name = name == "hanami" ? "hanami" : "hanami-#{name}"
29
+
30
+ %(gem "#{gem_name}", #{hanami_version(name)})
31
+ end
32
+
26
33
  # @since 2.0.0
27
34
  # @api private
28
- def hanami_version
29
- Version.gem_requirement
35
+ def hanami_version(gem_name)
36
+ if hanami_head?
37
+ %(github: "hanami/#{gem_name}", branch: "main")
38
+ else
39
+ %("#{Version.gem_requirement}")
40
+ end
30
41
  end
31
42
 
32
43
  # @since 2.0.0
@@ -41,11 +52,49 @@ module Hanami
41
52
  inflector.underscore(app)
42
53
  end
43
54
 
55
+ # @since 2.1.0
56
+ # @api private
57
+ def humanized_app_name
58
+ inflector.humanize(app)
59
+ end
60
+
61
+ # @since 2.1.0
62
+ # @api private
63
+ def hanami_head?
64
+ options.fetch(:head)
65
+ end
66
+
67
+ # @since 2.1.0
68
+ # @api private
69
+ def generate_assets?
70
+ !options.fetch(:skip_assets, false)
71
+ end
72
+
73
+ # @since 2.1.0
74
+ # @api private
75
+ def bundled_views?
76
+ Hanami.bundled?("hanami-view")
77
+ end
78
+
79
+ # @since 2.1.0
80
+ # @api private
81
+ def bundled_assets?
82
+ Hanami.bundled?("hanami-assets")
83
+ end
84
+
44
85
  private
45
86
 
87
+ # @since 2.0.0
88
+ # @api private
46
89
  attr_reader :inflector
47
90
 
91
+ # @since 2.0.0
92
+ # @api private
48
93
  attr_reader :app
94
+
95
+ # @since 2.1.0
96
+ # @api private
97
+ attr_reader :options
49
98
  end
50
99
  end
51
100
  end
@@ -0,0 +1,5 @@
1
+ body {
2
+ background-color: #fff;
3
+ color: #000;
4
+ font-family: sans-serif;
5
+ }
@@ -0,0 +1 @@
1
+ import "../css/app.css";
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title><%= humanized_app_name %></title>
7
+ <%- if generate_assets? -%>
8
+ <%%= favicon %>
9
+ <%%= css "app" %>
10
+ <%- end -%>
11
+ </head>
12
+ <body>
13
+ <%%= yield %>
14
+ <%- if generate_assets? -%>
15
+ <%%= js "app" %>
16
+ <%- end -%>
17
+ </body>
18
+ </html>
@@ -2,25 +2,31 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "hanami", "<%= hanami_version %>"
6
- gem "hanami-router", "<%= hanami_version %>"
7
- gem "hanami-controller", "<%= hanami_version %>"
8
- gem "hanami-validations", "<%= hanami_version %>"
9
- gem "hanami-view", "<%= hanami_version %>"
10
- gem "hanami-webconsole", "<%= hanami_version %>"
5
+ <%= hanami_gem("hanami") %>
6
+ <%= hanami_gem("router") %>
7
+ <%= hanami_gem("controller") %>
8
+ <%= hanami_gem("validations") %>
9
+ <%= hanami_gem("view") %>
10
+ <%- if generate_assets? -%>
11
+ <%= hanami_gem("assets") %>
12
+ <%- end -%>
11
13
 
12
14
  gem "dry-types", "~> 1.0", ">= 1.6.1"
13
15
  gem "puma"
14
16
  gem "rake"
15
17
 
18
+ group :development do
19
+ <%= hanami_gem("webconsole") %>
20
+ end
21
+
16
22
  group :development, :test do
17
23
  gem "dotenv"
18
24
  end
19
25
 
20
26
  group :cli, :development do
21
- gem "hanami-reloader"
27
+ <%= hanami_gem("reloader") %>
22
28
  end
23
29
 
24
30
  group :cli, :development, :test do
25
- gem "hanami-rspec"
31
+ <%= hanami_gem("rspec") %>
26
32
  end
@@ -1,2 +1,6 @@
1
1
  .env
2
2
  log/*
3
+ <%- if generate_assets? -%>
4
+ public/
5
+ node_modules/
6
+ <%- end -%>
@@ -0,0 +1,4 @@
1
+ web: bundle exec hanami server
2
+ <%- if generate_assets? -%>
3
+ assets: bundle exec hanami assets watch
4
+ <%- end -%>
@@ -40,6 +40,7 @@ module Hanami
40
40
  fs.write("README.md", t("readme.erb", context))
41
41
  fs.write("Gemfile", t("gemfile.erb", context))
42
42
  fs.write("Rakefile", t("rakefile.erb", context))
43
+ fs.write("Procfile.dev", t("procfile.erb", context))
43
44
  fs.write("config.ru", t("config_ru.erb", context))
44
45
 
45
46
  fs.write("config/app.rb", t("app.erb", context))
@@ -54,7 +55,13 @@ module Hanami
54
55
  fs.write("app/action.rb", t("action.erb", context))
55
56
  fs.write("app/view.rb", t("view.erb", context))
56
57
  fs.write("app/views/helpers.rb", t("helpers.erb", context))
57
- fs.write("app/templates/layouts/app.html.erb", File.read(File.join(__dir__, "app", "layouts_app.html.erb")))
58
+ fs.write("app/templates/layouts/app.html.erb", t("app_layout.erb", context))
59
+
60
+ if context.generate_assets?
61
+ fs.write("app/assets/js/app.js", t("app_js.erb", context))
62
+ fs.write("app/assets/css/app.css", t("app_css.erb", context))
63
+ fs.write("app/assets/images/favicon.ico", File.read(File.join(__dir__, "app", "favicon.ico")))
64
+ end
58
65
 
59
66
  fs.write("public/404.html", File.read(File.join(__dir__, "app", "404.html")))
60
67
  fs.write("public/500.html", File.read(File.join(__dir__, "app", "500.html")))
@@ -64,7 +71,8 @@ module Hanami
64
71
  require "erb"
65
72
 
66
73
  ERB.new(
67
- File.read(File.join(__dir__, "app", path))
74
+ File.read(File.join(__dir__, "app", path)),
75
+ trim_mode: "-"
68
76
  ).result(context.ctx)
69
77
  end
70
78
 
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+
5
+ module Hanami
6
+ module CLI
7
+ # @api private
8
+ # @since 2.1.0
9
+ class InteractiveSystemCall
10
+ # @api private
11
+ # @since 2.1.0
12
+ def initialize(out: $stdout, err: $stderr)
13
+ @out = out
14
+ @err = err
15
+ super()
16
+ end
17
+
18
+ # @api private
19
+ # @since 2.1.0
20
+ def call(cmd, *args, env: {})
21
+ ::Bundler.with_unbundled_env do
22
+ threads = []
23
+ exit_status = 0
24
+
25
+ # rubocop:disable Lint/SuppressedException
26
+ Open3.popen3(env, command(cmd, *args)) do |_stdin, stdout, stderr, wait_thr|
27
+ threads << Thread.new do
28
+ stdout.each_line do |line|
29
+ out.puts(line)
30
+ end
31
+ rescue IOError # FIXME: Check if this is legit
32
+ end
33
+
34
+ threads << Thread.new do
35
+ stderr.each_line do |line|
36
+ err.puts(line)
37
+ end
38
+ rescue IOError # FIXME: Check if this is legit
39
+ end
40
+
41
+ threads.each(&:join)
42
+
43
+ exit_status = wait_thr.value
44
+ end
45
+ # rubocop:enable Lint/SuppressedException
46
+
47
+ exit(exit_status.exitstatus)
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ # @api private
54
+ # @since 2.1.0
55
+ attr_reader :out, :err
56
+
57
+ # @since 2.1.0
58
+ # @api public
59
+ def command(cmd, *args)
60
+ [cmd, args].flatten(1).compact.join(" ")
61
+ end
62
+ end
63
+ end
64
+ end
@@ -85,13 +85,13 @@ module Hanami
85
85
  #
86
86
  # @since 2.0.0
87
87
  # @api public
88
- def call(cmd, env: {})
88
+ def call(cmd, *args, env: {})
89
89
  exitstatus = nil
90
90
  out = nil
91
91
  err = nil
92
92
 
93
93
  ::Bundler.with_unbundled_env do
94
- Open3.popen3(env, cmd) do |stdin, stdout, stderr, wait_thr|
94
+ Open3.popen3(env, command(cmd, *args)) do |stdin, stdout, stderr, wait_thr|
95
95
  yield stdin, stdout, stderr, wait_thr if block_given?
96
96
 
97
97
  stdin.close
@@ -104,6 +104,12 @@ module Hanami
104
104
 
105
105
  Result.new(exit_code: exitstatus, out: out, err: err)
106
106
  end
107
+
108
+ # @since 2.1.0
109
+ # @api public
110
+ def command(cmd, *args)
111
+ [cmd, args].flatten(1).compact.join(" ")
112
+ end
107
113
  end
108
114
  end
109
115
  end
@@ -6,6 +6,6 @@ module Hanami
6
6
  #
7
7
  # @api public
8
8
  # @since 2.0.0
9
- VERSION = "2.1.0.beta1"
9
+ VERSION = "2.1.0.beta2"
10
10
  end
11
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0.beta1
4
+ version: 2.1.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-29 00:00:00.000000000 Z
11
+ date: 2023-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,7 +53,7 @@ dependencies:
53
53
  version: '1.0'
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
- version: 1.0.1
56
+ version: 1.0.2
57
57
  - - "<"
58
58
  - !ruby/object:Gem::Version
59
59
  version: '2'
@@ -66,7 +66,7 @@ dependencies:
66
66
  version: '1.0'
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: 1.0.1
69
+ version: 1.0.2
70
70
  - - "<"
71
71
  - !ruby/object:Gem::Version
72
72
  version: '2'
@@ -191,6 +191,10 @@ files:
191
191
  - lib/hanami/cli/command.rb
192
192
  - lib/hanami/cli/commands.rb
193
193
  - lib/hanami/cli/commands/app.rb
194
+ - lib/hanami/cli/commands/app/assets.rb
195
+ - lib/hanami/cli/commands/app/assets/command.rb
196
+ - lib/hanami/cli/commands/app/assets/compile.rb
197
+ - lib/hanami/cli/commands/app/assets/watch.rb
194
198
  - lib/hanami/cli/commands/app/command.rb
195
199
  - lib/hanami/cli/commands/app/console.rb
196
200
  - lib/hanami/cli/commands/app/db/create.rb
@@ -209,6 +213,7 @@ files:
209
213
  - lib/hanami/cli/commands/app/db/utils/postgres.rb
210
214
  - lib/hanami/cli/commands/app/db/utils/sqlite.rb
211
215
  - lib/hanami/cli/commands/app/db/version.rb
216
+ - lib/hanami/cli/commands/app/dev.rb
212
217
  - lib/hanami/cli/commands/app/generate.rb
213
218
  - lib/hanami/cli/commands/app/generate/action.rb
214
219
  - lib/hanami/cli/commands/app/generate/slice.rb
@@ -234,10 +239,12 @@ files:
234
239
  - lib/hanami/cli/generators/app/action_context.rb
235
240
  - lib/hanami/cli/generators/app/slice.rb
236
241
  - lib/hanami/cli/generators/app/slice/action.erb
242
+ - lib/hanami/cli/generators/app/slice/app_css.erb
243
+ - lib/hanami/cli/generators/app/slice/app_js.erb
244
+ - lib/hanami/cli/generators/app/slice/app_layout.erb
237
245
  - lib/hanami/cli/generators/app/slice/entities.erb
238
246
  - lib/hanami/cli/generators/app/slice/helpers.erb
239
247
  - lib/hanami/cli/generators/app/slice/keep.erb
240
- - lib/hanami/cli/generators/app/slice/layouts_app.html.erb
241
248
  - lib/hanami/cli/generators/app/slice/repository.erb
242
249
  - lib/hanami/cli/generators/app/slice/routes.erb
243
250
  - lib/hanami/cli/generators/app/slice/slice.erb
@@ -255,13 +262,17 @@ files:
255
262
  - lib/hanami/cli/generators/gem/app/500.html
256
263
  - lib/hanami/cli/generators/gem/app/action.erb
257
264
  - lib/hanami/cli/generators/gem/app/app.erb
265
+ - lib/hanami/cli/generators/gem/app/app_css.erb
266
+ - lib/hanami/cli/generators/gem/app/app_js.erb
267
+ - lib/hanami/cli/generators/gem/app/app_layout.erb
258
268
  - lib/hanami/cli/generators/gem/app/config_ru.erb
259
269
  - lib/hanami/cli/generators/gem/app/env.erb
270
+ - lib/hanami/cli/generators/gem/app/favicon.ico
260
271
  - lib/hanami/cli/generators/gem/app/gemfile.erb
261
272
  - lib/hanami/cli/generators/gem/app/gitignore.erb
262
273
  - lib/hanami/cli/generators/gem/app/helpers.erb
263
274
  - lib/hanami/cli/generators/gem/app/keep.erb
264
- - lib/hanami/cli/generators/gem/app/layouts_app.html.erb
275
+ - lib/hanami/cli/generators/gem/app/procfile.erb
265
276
  - lib/hanami/cli/generators/gem/app/puma.erb
266
277
  - lib/hanami/cli/generators/gem/app/rakefile.erb
267
278
  - lib/hanami/cli/generators/gem/app/readme.erb
@@ -271,6 +282,7 @@ files:
271
282
  - lib/hanami/cli/generators/gem/app/validator.erb
272
283
  - lib/hanami/cli/generators/gem/app/view.erb
273
284
  - lib/hanami/cli/generators/version.rb
285
+ - lib/hanami/cli/interactive_system_call.rb
274
286
  - lib/hanami/cli/middleware_stack_inspector.rb
275
287
  - lib/hanami/cli/naming.rb
276
288
  - lib/hanami/cli/rake_tasks.rb
@@ -1 +0,0 @@
1
- <%= yield %>
@@ -1 +0,0 @@
1
- <%= yield %>