hanami-cli 2.1.0.beta1 → 2.1.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
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 %>