hanami-cli 2.0.3 → 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 +33 -0
- data/Gemfile +3 -2
- data/LICENSE.md +1 -1
- data/README.md +1 -1
- data/hanami-cli.gemspec +1 -1
- data/lib/hanami/cli/bundler.rb +21 -7
- 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/db/rollback.rb +30 -6
- data/lib/hanami/cli/commands/app/db/utils/database.rb +5 -1
- data/lib/hanami/cli/commands/app/dev.rb +57 -0
- data/lib/hanami/cli/commands/app/generate/action.rb +5 -4
- data/lib/hanami/cli/commands/app/generate/view.rb +57 -0
- data/lib/hanami/cli/commands/app/generate.rb +2 -2
- data/lib/hanami/cli/commands/app/install.rb +44 -1
- data/lib/hanami/cli/commands/app.rb +9 -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/slice_template.html.erb +1 -0
- data/lib/hanami/cli/generators/app/action/slice_view.erb +10 -0
- data/lib/hanami/cli/generators/app/action/template.html.erb +1 -2
- data/lib/hanami/cli/generators/app/action/view.erb +2 -5
- data/lib/hanami/cli/generators/app/action.rb +34 -22
- data/lib/hanami/cli/generators/app/action_context.rb +1 -1
- 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/helpers.erb +10 -0
- data/lib/hanami/cli/generators/app/slice/view.erb +0 -2
- data/lib/hanami/cli/generators/app/slice.rb +15 -6
- data/lib/hanami/cli/generators/app/slice_context.rb +18 -0
- data/lib/hanami/cli/generators/app/view/app_template.html.erb +1 -0
- data/lib/hanami/cli/generators/app/view/app_view.erb +10 -0
- data/lib/hanami/cli/generators/app/view/slice_template.html.erb +1 -0
- data/lib/hanami/cli/generators/app/view/slice_view.erb +10 -0
- data/lib/hanami/cli/generators/app/view.rb +89 -0
- data/lib/hanami/cli/generators/app/view_context.rb +100 -0
- data/lib/hanami/cli/generators/context.rb +53 -4
- data/lib/hanami/cli/generators/gem/app/404.html +11 -0
- data/lib/hanami/cli/generators/gem/app/500.html +11 -0
- 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 -6
- data/lib/hanami/cli/generators/gem/app/gitignore.erb +4 -0
- data/lib/hanami/cli/generators/gem/app/helpers.erb +10 -0
- data/lib/hanami/cli/generators/gem/app/procfile.erb +4 -0
- data/lib/hanami/cli/generators/gem/app/puma.erb +5 -3
- data/lib/hanami/cli/generators/gem/app/view.erb +9 -0
- data/lib/hanami/cli/generators/gem/app.rb +15 -1
- data/lib/hanami/cli/interactive_system_call.rb +64 -0
- data/lib/hanami/cli/system_call.rb +8 -2
- data/lib/hanami/cli/url.rb +1 -1
- data/lib/hanami/cli/version.rb +1 -1
- metadata +35 -7
@@ -14,14 +14,23 @@ 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
|
33
|
+
prefix.register "view", Generate::View
|
25
34
|
end
|
26
35
|
end
|
27
36
|
end
|
@@ -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 %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1><%= camelized_slice_name %>::Views::<%= camelized_controller_name %>::<%= camelized_action_name %></h1>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module <%= camelized_slice_name %>
|
4
|
+
module Views
|
5
|
+
<%= module_controller_declaration %>
|
6
|
+
<%= module_controller_offset %>class <%= camelized_action_name %> < <%= camelized_slice_name %>::View
|
7
|
+
<%= module_controller_offset %>end
|
8
|
+
<%= module_controller_end %>
|
9
|
+
end
|
10
|
+
end
|
@@ -1,2 +1 @@
|
|
1
|
-
<h1><%=
|
2
|
-
<h2><%= template_path %></h2>
|
1
|
+
<h1><%= camelized_app_name %>::Views::<%= camelized_controller_name %>::<%= camelized_action_name %></h1>
|
@@ -1,12 +1,9 @@
|
|
1
|
-
# auto_register: false
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
module <%= camelized_slice_name %>
|
3
|
+
module <%= camelized_app_name %>
|
7
4
|
module Views
|
8
5
|
<%= module_controller_declaration %>
|
9
|
-
<%= module_controller_offset %>class <%= camelized_action_name %> < <%=
|
6
|
+
<%= module_controller_offset %>class <%= camelized_action_name %> < <%= camelized_app_name %>::View
|
10
7
|
<%= module_controller_offset %>end
|
11
8
|
<%= module_controller_end %>
|
12
9
|
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
|
@@ -66,7 +63,8 @@ module Hanami
|
|
66
63
|
|
67
64
|
attr_reader :inflector
|
68
65
|
|
69
|
-
|
66
|
+
# rubocop:disable Metrics/AbcSize
|
67
|
+
def generate_for_slice(controller, action, url, http, format, skip_view, slice, context)
|
70
68
|
slice_directory = fs.join("slices", slice)
|
71
69
|
raise MissingSliceError.new(slice) unless fs.directory?(slice_directory)
|
72
70
|
|
@@ -79,16 +77,17 @@ module Hanami
|
|
79
77
|
fs.mkdir(directory = fs.join(slice_directory, "actions", controller))
|
80
78
|
fs.write(fs.join(directory, "#{action}.rb"), t("slice_action.erb", context))
|
81
79
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
80
|
+
unless skip_view
|
81
|
+
fs.mkdir(directory = fs.join(slice_directory, "views", controller))
|
82
|
+
fs.write(fs.join(directory, "#{action}.rb"), t("slice_view.erb", context))
|
83
|
+
|
84
|
+
fs.mkdir(directory = fs.join(slice_directory, "templates", controller))
|
85
|
+
fs.write(fs.join(directory, "#{action}.#{format}.erb"),
|
86
|
+
t(template_with_format_ext("slice_template", format), context))
|
87
|
+
end
|
89
88
|
end
|
90
89
|
|
91
|
-
def generate_for_app(controller, action, url, http,
|
90
|
+
def generate_for_app(controller, action, url, http, format, skip_view, context)
|
92
91
|
fs.inject_line_at_class_bottom(
|
93
92
|
fs.join("config", "routes.rb"),
|
94
93
|
"class Routes",
|
@@ -97,7 +96,17 @@ module Hanami
|
|
97
96
|
|
98
97
|
fs.mkdir(directory = fs.join("app", "actions", controller))
|
99
98
|
fs.write(fs.join(directory, "#{action}.rb"), t("action.erb", context))
|
99
|
+
|
100
|
+
unless skip_view
|
101
|
+
fs.mkdir(directory = fs.join("app", "views", controller))
|
102
|
+
fs.write(fs.join(directory, "#{action}.rb"), t("view.erb", context))
|
103
|
+
|
104
|
+
fs.mkdir(directory = fs.join("app", "templates", controller))
|
105
|
+
fs.write(fs.join(directory, "#{action}.#{format}.erb"),
|
106
|
+
t(template_with_format_ext("template", format), context))
|
107
|
+
end
|
100
108
|
end
|
109
|
+
# rubocop:enable Metrics/AbcSize
|
101
110
|
|
102
111
|
def slice_matcher(slice)
|
103
112
|
/slice[[:space:]]*:#{slice}/
|
@@ -108,20 +117,23 @@ module Hanami
|
|
108
117
|
http)} "#{route_url(controller, action, url)}", to: "#{controller.join('.')}.#{action}")
|
109
118
|
end
|
110
119
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
120
|
+
def template_with_format_ext(name, format)
|
121
|
+
ext =
|
122
|
+
case format.to_sym
|
123
|
+
when :html
|
124
|
+
".html.erb"
|
125
|
+
else
|
126
|
+
".erb"
|
127
|
+
end
|
128
|
+
|
129
|
+
"#{name}#{ext}"
|
118
130
|
end
|
119
131
|
|
120
132
|
def template(path, context)
|
121
133
|
require "erb"
|
122
134
|
|
123
135
|
ERB.new(
|
124
|
-
File.read(__dir__ + "/action/#{path}")
|
136
|
+
File.read(__dir__ + "/action/#{path}"), trim_mode: "-",
|
125
137
|
).result(context.ctx)
|
126
138
|
end
|
127
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>
|
@@ -19,7 +19,7 @@ module Hanami
|
|
19
19
|
|
20
20
|
# @since 2.0.0
|
21
21
|
# @api private
|
22
|
-
def call(app, slice, url, context: SliceContext.new(inflector, app, slice, url))
|
22
|
+
def call(app, slice, url, context: SliceContext.new(inflector, app, slice, url)) # rubocop:disable Metrics/AbcSize
|
23
23
|
fs.inject_line_at_class_bottom(
|
24
24
|
fs.join("config", "routes.rb"), "class Routes", t("routes.erb", context).chomp
|
25
25
|
)
|
@@ -28,14 +28,22 @@ module Hanami
|
|
28
28
|
|
29
29
|
# fs.write("#{directory}/config/slice.rb", t("slice.erb", context))
|
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
|
+
fs.write(fs.join(directory, "views", "helpers.rb"), t("helpers.erb", context))
|
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
|
+
|
32
40
|
# fs.write(fs.join(directory, "/entities.rb"), t("entities.erb", context))
|
33
41
|
# fs.write(fs.join(directory, "/repository.rb"), t("repository.erb", context))
|
34
42
|
|
35
43
|
fs.write(fs.join(directory, "actions/.keep"), t("keep.erb", context))
|
36
|
-
|
37
|
-
|
38
|
-
|
44
|
+
fs.write(fs.join(directory, "views/.keep"), t("keep.erb", context))
|
45
|
+
fs.write(fs.join(directory, "templates/.keep"), t("keep.erb", context))
|
46
|
+
fs.write(fs.join(directory, "templates/layouts/.keep"), t("keep.erb", context))
|
39
47
|
# fs.write(fs.join(directory, entities/.keep"), t("keep.erb", context))
|
40
48
|
# fs.write(fs.join(directory, repositories/.keep"), t("keep.erb", context))
|
41
49
|
end
|
@@ -50,7 +58,8 @@ module Hanami
|
|
50
58
|
require "erb"
|
51
59
|
|
52
60
|
ERB.new(
|
53
|
-
File.read(__dir__ + "/slice/#{path}")
|
61
|
+
File.read(__dir__ + "/slice/#{path}"),
|
62
|
+
trim_mode: "-"
|
54
63
|
).result(context.ctx)
|
55
64
|
end
|
56
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
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1><%= camelized_app_name %>::Views::<%= camelized_namespace %>::<%= camelized_name %></h1>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module <%= camelized_app_name %>
|
4
|
+
module Views
|
5
|
+
<%= module_namespace_declaration %>
|
6
|
+
<%= module_namespace_offset %>class <%= camelized_name %> < <%= camelized_app_name %>::View
|
7
|
+
<%= module_namespace_offset %>end
|
8
|
+
<%= module_namespace_end %>
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1><%= camelized_slice_name %>::Views::<%= camelized_namespace %>::<%= camelized_name %></h1>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module <%= camelized_slice_name %>
|
4
|
+
module Views
|
5
|
+
<%= module_namespace_declaration %>
|
6
|
+
<%= module_namespace_offset %>class <%= camelized_name %> < <%= camelized_slice_name %>::View
|
7
|
+
<%= module_namespace_offset %>end
|
8
|
+
<%= module_namespace_end %>
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "erb"
|
4
|
+
require "dry/files"
|
5
|
+
require_relative "../../errors"
|
6
|
+
|
7
|
+
module Hanami
|
8
|
+
module CLI
|
9
|
+
module Generators
|
10
|
+
module App
|
11
|
+
# @since 2.0.0
|
12
|
+
# @api private
|
13
|
+
class View
|
14
|
+
# @since 2.0.0
|
15
|
+
# @api private
|
16
|
+
def initialize(fs:, inflector:)
|
17
|
+
@fs = fs
|
18
|
+
@inflector = inflector
|
19
|
+
end
|
20
|
+
|
21
|
+
# @since 2.0.0
|
22
|
+
# @api private
|
23
|
+
def call(app, key, format, slice)
|
24
|
+
context = ViewContext.new(inflector, app, slice, key)
|
25
|
+
|
26
|
+
if slice
|
27
|
+
generate_for_slice(context, format, slice)
|
28
|
+
else
|
29
|
+
generate_for_app(context, format, slice)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
attr_reader :fs
|
36
|
+
|
37
|
+
attr_reader :inflector
|
38
|
+
|
39
|
+
# rubocop:disable Metrics/AbcSize
|
40
|
+
|
41
|
+
def generate_for_slice(context, format, slice)
|
42
|
+
slice_directory = fs.join("slices", slice)
|
43
|
+
raise MissingSliceError.new(slice) unless fs.directory?(slice_directory)
|
44
|
+
|
45
|
+
fs.mkdir(directory = fs.join(slice_directory, "views", context.namespaces))
|
46
|
+
fs.write(fs.join(directory, "#{context.name}.rb"), t("slice_view.erb", context))
|
47
|
+
|
48
|
+
fs.mkdir(directory = fs.join(slice_directory, "templates", context.namespaces))
|
49
|
+
fs.write(fs.join(directory, "#{context.name}.#{format}.erb"),
|
50
|
+
t(template_with_format_ext("slice_template", format), context))
|
51
|
+
end
|
52
|
+
|
53
|
+
def generate_for_app(context, format, _slice)
|
54
|
+
fs.mkdir(directory = fs.join("app", "views", context.namespaces))
|
55
|
+
fs.write(fs.join(directory, "#{context.name}.rb"), t("app_view.erb", context))
|
56
|
+
|
57
|
+
fs.mkdir(directory = fs.join("app", "templates", context.namespaces))
|
58
|
+
fs.write(fs.join(directory, "#{context.name}.#{format}.erb"),
|
59
|
+
t(template_with_format_ext("app_template", format), context))
|
60
|
+
end
|
61
|
+
|
62
|
+
# rubocop:enable Metrics/AbcSize
|
63
|
+
|
64
|
+
def template_with_format_ext(name, format)
|
65
|
+
ext =
|
66
|
+
case format.to_sym
|
67
|
+
when :html
|
68
|
+
".html.erb"
|
69
|
+
else
|
70
|
+
".erb"
|
71
|
+
end
|
72
|
+
|
73
|
+
"#{name}#{ext}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def template(path, context)
|
77
|
+
require "erb"
|
78
|
+
|
79
|
+
ERB.new(
|
80
|
+
File.read(__dir__ + "/view/#{path}")
|
81
|
+
).result(context.ctx)
|
82
|
+
end
|
83
|
+
|
84
|
+
alias_method :t, :template
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|