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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/Gemfile +3 -2
- data/hanami-cli.gemspec +1 -1
- data/lib/hanami/cli/bundler.rb +19 -5
- data/lib/hanami/cli/command.rb +4 -4
- data/lib/hanami/cli/commands/app/assets/command.rb +82 -0
- data/lib/hanami/cli/commands/app/assets/compile.rb +32 -0
- data/lib/hanami/cli/commands/app/assets/watch.rb +36 -0
- data/lib/hanami/cli/commands/app/assets.rb +16 -0
- data/lib/hanami/cli/commands/app/command.rb +2 -2
- data/lib/hanami/cli/commands/app/dev.rb +57 -0
- data/lib/hanami/cli/commands/app/generate/action.rb +3 -2
- data/lib/hanami/cli/commands/app/install.rb +44 -1
- data/lib/hanami/cli/commands/app.rb +8 -0
- data/lib/hanami/cli/commands/gem/new.rb +41 -7
- data/lib/hanami/cli/errors.rb +30 -0
- data/lib/hanami/cli/files.rb +8 -2
- data/lib/hanami/cli/generators/app/action/action.erb +5 -1
- data/lib/hanami/cli/generators/app/action/slice_action.erb +5 -1
- data/lib/hanami/cli/generators/app/action.rb +3 -6
- data/lib/hanami/cli/generators/app/slice/app_css.erb +5 -0
- data/lib/hanami/cli/generators/app/slice/app_js.erb +1 -0
- data/lib/hanami/cli/generators/app/slice/app_layout.erb +18 -0
- data/lib/hanami/cli/generators/app/slice.rb +9 -3
- data/lib/hanami/cli/generators/app/slice_context.rb +18 -0
- data/lib/hanami/cli/generators/context.rb +52 -3
- data/lib/hanami/cli/generators/gem/app/app_css.erb +5 -0
- data/lib/hanami/cli/generators/gem/app/app_js.erb +1 -0
- data/lib/hanami/cli/generators/gem/app/app_layout.erb +18 -0
- data/lib/hanami/cli/generators/gem/app/favicon.ico +0 -0
- data/lib/hanami/cli/generators/gem/app/gemfile.erb +14 -8
- data/lib/hanami/cli/generators/gem/app/gitignore.erb +4 -0
- data/lib/hanami/cli/generators/gem/app/procfile.erb +4 -0
- data/lib/hanami/cli/generators/gem/app.rb +10 -2
- data/lib/hanami/cli/interactive_system_call.rb +64 -0
- data/lib/hanami/cli/system_call.rb +8 -2
- data/lib/hanami/cli/version.rb +1 -1
- metadata +18 -6
- data/lib/hanami/cli/generators/app/slice/layouts_app.html.erb +0 -1
- 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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 85a528645e9205c15ccdf4b81cc32a3fb0789a8a7f07c56554c1b8b0e66b9e91
|
|
4
|
+
data.tar.gz: 5937fd333d11a7f5131d0298dc609c8a92e233249bc0b2e9e8f28705977f20b4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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-
|
|
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.
|
|
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"
|
data/lib/hanami/cli/bundler.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require "bundler"
|
|
4
4
|
require "open3"
|
|
5
5
|
require "etc"
|
|
6
|
-
|
|
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 [
|
|
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:
|
|
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 [
|
|
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 [
|
|
144
|
+
# @return [Hanami::CLI::Files]
|
|
131
145
|
#
|
|
132
146
|
# @since 2.0.0
|
|
133
147
|
# @api public
|
data/lib/hanami/cli/command.rb
CHANGED
|
@@ -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 [
|
|
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:
|
|
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 [
|
|
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
|
|
@@ -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:
|
|
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
|
-
|
|
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",
|
|
26
|
-
"bookshelf --
|
|
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
|
-
|
|
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
|
-
|
|
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
|
data/lib/hanami/cli/errors.rb
CHANGED
|
@@ -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")
|
data/lib/hanami/cli/files.rb
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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 @@
|
|
|
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
|
-
|
|
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
|
-
|
|
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 @@
|
|
|
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>
|
|
Binary file
|
|
@@ -2,25 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
27
|
+
<%= hanami_gem("reloader") %>
|
|
22
28
|
end
|
|
23
29
|
|
|
24
30
|
group :cli, :development, :test do
|
|
25
|
-
|
|
31
|
+
<%= hanami_gem("rspec") %>
|
|
26
32
|
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",
|
|
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
|
data/lib/hanami/cli/version.rb
CHANGED
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.
|
|
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-
|
|
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.
|
|
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.
|
|
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/
|
|
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 %>
|