hanami-cli 2.2.1 → 2.3.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/.github/workflows/ci.yml +9 -1
- data/CHANGELOG.md +50 -0
- data/Gemfile +3 -1
- data/hanami-cli.gemspec +3 -1
- data/lib/hanami/cli/command.rb +5 -11
- data/lib/hanami/cli/commands/app/command.rb +5 -5
- data/lib/hanami/cli/commands/app/console.rb +1 -0
- data/lib/hanami/cli/commands/app/db/command.rb +0 -1
- data/lib/hanami/cli/commands/app/db/drop.rb +2 -2
- data/lib/hanami/cli/commands/app/db/rollback.rb +204 -0
- data/lib/hanami/cli/commands/app/db/utils/mysql.rb +3 -2
- data/lib/hanami/cli/commands/app/db/utils/postgres.rb +3 -1
- data/lib/hanami/cli/commands/app/generate/action.rb +32 -40
- data/lib/hanami/cli/commands/app/generate/command.rb +54 -17
- data/lib/hanami/cli/commands/app/generate/component.rb +4 -19
- data/lib/hanami/cli/commands/app/generate/part.rb +4 -21
- data/lib/hanami/cli/commands/app/generate/slice.rb +2 -2
- data/lib/hanami/cli/commands/app/generate/view.rb +5 -24
- data/lib/hanami/cli/commands/app/run.rb +108 -0
- data/lib/hanami/cli/commands/app/server.rb +0 -1
- data/lib/hanami/cli/commands/app.rb +2 -0
- data/lib/hanami/cli/commands/gem/new.rb +34 -3
- data/lib/hanami/cli/errors.rb +26 -0
- data/lib/hanami/cli/files.rb +20 -6
- data/lib/hanami/cli/generators/app/action.rb +83 -100
- data/lib/hanami/cli/generators/app/component.rb +11 -33
- data/lib/hanami/cli/generators/app/migration.rb +1 -1
- data/lib/hanami/cli/generators/app/operation.rb +4 -5
- data/lib/hanami/cli/generators/app/part.rb +42 -65
- data/lib/hanami/cli/generators/app/relation.rb +5 -6
- data/lib/hanami/cli/generators/app/repo.rb +3 -5
- data/lib/hanami/cli/generators/app/ruby_class_file.rb +32 -0
- data/lib/hanami/cli/generators/app/ruby_file.rb +123 -0
- data/lib/hanami/cli/generators/app/ruby_module_file.rb +28 -0
- data/lib/hanami/cli/generators/app/slice.rb +130 -37
- data/lib/hanami/cli/generators/app/struct.rb +3 -4
- data/lib/hanami/cli/generators/app/view.rb +40 -45
- data/lib/hanami/cli/generators/constants.rb +1 -1
- data/lib/hanami/cli/generators/context.rb +6 -0
- data/lib/hanami/cli/generators/gem/app/assets.js +14 -13
- data/lib/hanami/cli/generators/gem/app/dev +1 -1
- data/lib/hanami/cli/generators/gem/app/gemfile.erb +5 -0
- data/lib/hanami/cli/generators/gem/app/gitignore.erb +3 -1
- data/lib/hanami/cli/generators/gem/app/rakefile.erb +3 -0
- data/lib/hanami/cli/generators/gem/app/readme.erb +14 -0
- data/lib/hanami/cli/generators/gem/app/types.erb +1 -1
- data/lib/hanami/cli/generators/gem/app.rb +40 -37
- data/lib/hanami/cli/ruby_file_generator.rb +17 -8
- data/lib/hanami/cli/server.rb +15 -1
- data/lib/hanami/cli/version.rb +1 -1
- data/lib/hanami/console/context.rb +5 -0
- metadata +37 -42
- data/lib/hanami/cli/generators/app/action/action.erb +0 -17
- data/lib/hanami/cli/generators/app/action/slice_action.erb +0 -17
- data/lib/hanami/cli/generators/app/action/slice_template.html.erb +0 -1
- data/lib/hanami/cli/generators/app/action/slice_view.erb +0 -10
- data/lib/hanami/cli/generators/app/action/template.erb +0 -0
- data/lib/hanami/cli/generators/app/action/template.html.erb +0 -1
- data/lib/hanami/cli/generators/app/action/view.erb +0 -10
- data/lib/hanami/cli/generators/app/action_context.rb +0 -90
- data/lib/hanami/cli/generators/app/component/component.erb +0 -8
- data/lib/hanami/cli/generators/app/component/slice_component.erb +0 -8
- data/lib/hanami/cli/generators/app/component_context.rb +0 -82
- data/lib/hanami/cli/generators/app/part/app_base_part.erb +0 -9
- data/lib/hanami/cli/generators/app/part/app_part.erb +0 -13
- data/lib/hanami/cli/generators/app/part/slice_base_part.erb +0 -9
- data/lib/hanami/cli/generators/app/part/slice_part.erb +0 -13
- data/lib/hanami/cli/generators/app/part_context.rb +0 -82
- data/lib/hanami/cli/generators/app/ruby_file_writer.rb +0 -151
- data/lib/hanami/cli/generators/app/slice/action.erb +0 -7
- data/lib/hanami/cli/generators/app/slice/app_css.erb +0 -5
- data/lib/hanami/cli/generators/app/slice/app_js.erb +0 -1
- data/lib/hanami/cli/generators/app/slice/app_layout.erb +0 -18
- data/lib/hanami/cli/generators/app/slice/helpers.erb +0 -10
- data/lib/hanami/cli/generators/app/slice/keep.erb +0 -0
- data/lib/hanami/cli/generators/app/slice/operation.erb +0 -7
- data/lib/hanami/cli/generators/app/slice/relation.erb +0 -8
- data/lib/hanami/cli/generators/app/slice/repo.erb +0 -8
- data/lib/hanami/cli/generators/app/slice/routes.erb +0 -3
- data/lib/hanami/cli/generators/app/slice/struct.erb +0 -8
- data/lib/hanami/cli/generators/app/slice/view.erb +0 -7
- data/lib/hanami/cli/generators/app/slice_context.rb +0 -72
- data/lib/hanami/cli/generators/app/view/app_template.html.erb +0 -1
- data/lib/hanami/cli/generators/app/view/app_view.erb +0 -10
- data/lib/hanami/cli/generators/app/view/slice_template.html.erb +0 -1
- data/lib/hanami/cli/generators/app/view/slice_view.erb +0 -10
- data/lib/hanami/cli/generators/app/view_context.rb +0 -88
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "erb"
|
|
4
3
|
require "dry/files"
|
|
4
|
+
require_relative "../constants"
|
|
5
5
|
require_relative "../../errors"
|
|
6
6
|
|
|
7
7
|
# rubocop:disable Metrics/ParameterLists
|
|
@@ -14,20 +14,25 @@ module Hanami
|
|
|
14
14
|
class Action
|
|
15
15
|
# @since 2.0.0
|
|
16
16
|
# @api private
|
|
17
|
-
def initialize(fs:, inflector:)
|
|
17
|
+
def initialize(fs:, inflector:, out: $stdout)
|
|
18
18
|
@fs = fs
|
|
19
19
|
@inflector = inflector
|
|
20
|
+
@out = out
|
|
21
|
+
@view_generator = Generators::App::View.new(
|
|
22
|
+
fs: fs,
|
|
23
|
+
inflector: inflector,
|
|
24
|
+
out: out
|
|
25
|
+
)
|
|
20
26
|
end
|
|
21
27
|
|
|
22
28
|
# @since 2.0.0
|
|
23
29
|
# @api private
|
|
24
|
-
def call(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
end
|
|
30
|
+
def call(key:, namespace:, base_path:, url_path:, http_method:, skip_view:, skip_route:, skip_tests:)
|
|
31
|
+
insert_route(key:, namespace:, url_path:, http_method:) unless skip_route
|
|
32
|
+
|
|
33
|
+
generate_action(key:, namespace:, base_path:, include_placeholder_body: skip_view)
|
|
34
|
+
|
|
35
|
+
generate_view(key:, namespace:, base_path:) unless skip_view
|
|
31
36
|
end
|
|
32
37
|
|
|
33
38
|
private
|
|
@@ -67,86 +72,82 @@ module Hanami
|
|
|
67
72
|
PATH_SEPARATOR = "/"
|
|
68
73
|
private_constant :PATH_SEPARATOR
|
|
69
74
|
|
|
70
|
-
attr_reader :fs
|
|
71
|
-
|
|
72
|
-
attr_reader :inflector
|
|
73
|
-
|
|
74
|
-
# rubocop:disable Metrics/AbcSize
|
|
75
|
-
def generate_for_slice(controller, action, url, http, format, skip_view, skip_route, slice, context)
|
|
76
|
-
slice_directory = fs.join("slices", slice)
|
|
77
|
-
raise MissingSliceError.new(slice) unless fs.directory?(slice_directory)
|
|
75
|
+
attr_reader :fs, :inflector, :out, :view_generator
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
fs.mkdir(directory = fs.join(slice_directory, "actions", controller))
|
|
88
|
-
fs.write(fs.join(directory, "#{action}.rb"), t("slice_action.erb", context))
|
|
77
|
+
# @api private
|
|
78
|
+
# @since 2.2.2
|
|
79
|
+
def insert_route(key:, namespace:, url_path:, http_method:)
|
|
80
|
+
routes_location = fs.join("config", "routes.rb")
|
|
81
|
+
route = route_definition(key:, url_path:, http_method:)
|
|
89
82
|
|
|
90
|
-
if
|
|
91
|
-
fs.
|
|
92
|
-
|
|
83
|
+
if namespace == Hanami.app.namespace
|
|
84
|
+
fs.inject_line_at_class_bottom(routes_location, "class Routes", route)
|
|
85
|
+
else
|
|
86
|
+
slice_routes = fs.join("slices", namespace, "config", "routes.rb")
|
|
93
87
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
if fs.exist?(slice_routes)
|
|
89
|
+
fs.inject_line_at_class_bottom(slice_routes, "class Routes", route)
|
|
90
|
+
else
|
|
91
|
+
slice_matcher = /slice[[:space:]]*:#{namespace}/
|
|
92
|
+
fs.inject_line_at_block_bottom(routes_location, slice_matcher, route)
|
|
93
|
+
end
|
|
97
94
|
end
|
|
98
95
|
end
|
|
99
96
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
97
|
+
# @api private
|
|
98
|
+
# @since 2.2.2
|
|
99
|
+
def generate_action(key:, namespace:, base_path:, include_placeholder_body:)
|
|
100
|
+
RubyClassFile.new(
|
|
101
|
+
fs: fs,
|
|
102
|
+
inflector: inflector,
|
|
103
|
+
namespace: namespace,
|
|
104
|
+
key: key,
|
|
105
|
+
base_path: base_path,
|
|
106
|
+
parent_class_name: "#{inflector.camelize(namespace)}::Action",
|
|
107
|
+
extra_namespace: "Actions",
|
|
108
|
+
body: [
|
|
109
|
+
"def handle(request, response)",
|
|
110
|
+
(" response.body = self.class.name" if include_placeholder_body),
|
|
111
|
+
"end"
|
|
112
|
+
].compact
|
|
113
|
+
).create
|
|
114
|
+
end
|
|
111
115
|
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
# @api private
|
|
117
|
+
# @since 2.2.2
|
|
118
|
+
def generate_view(key:, namespace:, base_path:)
|
|
119
|
+
*controller_name_parts, action_name = key.split(KEY_SEPARATOR)
|
|
114
120
|
|
|
115
|
-
|
|
116
|
-
fs.mkdir(view_directory)
|
|
117
|
-
fs.write(fs.join(view_directory, "#{view}.rb"), t("view.erb", context))
|
|
121
|
+
view_directory = fs.join(base_path, "views", controller_name_parts)
|
|
118
122
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
123
|
+
if generate_view?(action_name, view_directory)
|
|
124
|
+
view_generator.call(
|
|
125
|
+
key: key,
|
|
126
|
+
namespace: namespace,
|
|
127
|
+
base_path: base_path,
|
|
128
|
+
)
|
|
122
129
|
end
|
|
123
130
|
end
|
|
124
|
-
# rubocop:enable Metrics/AbcSize
|
|
125
|
-
|
|
126
|
-
def slice_matcher(slice)
|
|
127
|
-
/slice[[:space:]]*:#{slice}/
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def route(controller, action, url, http)
|
|
131
|
-
%(#{route_http(action,
|
|
132
|
-
http)} "#{route_url(controller, action, url)}", to: "#{controller.join('.')}.#{action}")
|
|
133
|
-
end
|
|
134
131
|
|
|
135
132
|
# @api private
|
|
136
|
-
# @since 2.
|
|
137
|
-
def
|
|
138
|
-
|
|
139
|
-
return generate_restful_view?(view, directory) if rest_view?(view)
|
|
133
|
+
# @since 2.2.2
|
|
134
|
+
def route_definition(key:, url_path:, http_method:)
|
|
135
|
+
*controller_name_parts, action_name = key.split(KEY_SEPARATOR)
|
|
140
136
|
|
|
141
|
-
|
|
137
|
+
method = route_http(action_name, http_method)
|
|
138
|
+
path = route_url(controller_name_parts, action_name, url_path)
|
|
139
|
+
|
|
140
|
+
%(#{method} "#{path}", to: "#{key}")
|
|
142
141
|
end
|
|
143
142
|
|
|
144
143
|
# @api private
|
|
145
|
-
# @since 2.
|
|
146
|
-
def
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
144
|
+
# @since 2.1.0
|
|
145
|
+
def generate_view?(action_name, directory)
|
|
146
|
+
if rest_view?(action_name)
|
|
147
|
+
generate_restful_view?(action_name, directory)
|
|
148
|
+
else
|
|
149
|
+
true
|
|
150
|
+
end
|
|
150
151
|
end
|
|
151
152
|
|
|
152
153
|
# @api private
|
|
@@ -169,40 +170,22 @@ module Hanami
|
|
|
169
170
|
RESTFUL_COUNTERPART_VIEWS.fetch(view, nil)
|
|
170
171
|
end
|
|
171
172
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
when :html
|
|
176
|
-
".html.erb"
|
|
177
|
-
else
|
|
178
|
-
".erb"
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
"#{name}#{ext}"
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
def template(path, context)
|
|
185
|
-
require "erb"
|
|
186
|
-
|
|
187
|
-
ERB.new(
|
|
188
|
-
File.read(__dir__ + "/action/#{path}"), trim_mode: "-",
|
|
189
|
-
).result(context.ctx)
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
alias_method :t, :template
|
|
193
|
-
|
|
194
|
-
def route_url(controller, action, url)
|
|
173
|
+
# @api private
|
|
174
|
+
# @since 2.1.0
|
|
175
|
+
def route_url(controller, action, url_path)
|
|
195
176
|
action = ROUTE_RESTFUL_URL_SUFFIXES.fetch(action) { [action] }
|
|
196
|
-
|
|
177
|
+
url_path ||= "#{PATH_SEPARATOR}#{(controller + action).join(PATH_SEPARATOR)}"
|
|
197
178
|
|
|
198
|
-
CLI::URL.call(
|
|
179
|
+
CLI::URL.call(url_path)
|
|
199
180
|
end
|
|
200
181
|
|
|
201
|
-
|
|
202
|
-
|
|
182
|
+
# @api private
|
|
183
|
+
# @since 2.1.0
|
|
184
|
+
def route_http(action, http_method)
|
|
185
|
+
result = (http_method ||= ROUTE_RESTFUL_HTTP_METHODS.fetch(action, ROUTE_DEFAULT_HTTP_METHOD)).downcase
|
|
203
186
|
|
|
204
187
|
unless ROUTE_HTTP_METHODS.include?(result)
|
|
205
|
-
raise UnknownHTTPMethodError.new(
|
|
188
|
+
raise UnknownHTTPMethodError.new(http_method)
|
|
206
189
|
end
|
|
207
190
|
|
|
208
191
|
result
|
|
@@ -12,49 +12,27 @@ module Hanami
|
|
|
12
12
|
class Component
|
|
13
13
|
# @api private
|
|
14
14
|
# @since 2.2.0
|
|
15
|
-
def initialize(fs:, inflector:)
|
|
15
|
+
def initialize(fs:, inflector:, out: $stdout)
|
|
16
16
|
@fs = fs
|
|
17
17
|
@inflector = inflector
|
|
18
|
+
@out = out
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
# @api private
|
|
21
22
|
# @since 2.2.0
|
|
22
|
-
def call(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
def call(key:, namespace:, base_path:)
|
|
24
|
+
RubyClassFile.new(
|
|
25
|
+
fs: fs,
|
|
26
|
+
inflector: inflector,
|
|
27
|
+
key: key,
|
|
28
|
+
namespace: namespace,
|
|
29
|
+
base_path: base_path,
|
|
30
|
+
).create
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
private
|
|
33
34
|
|
|
34
|
-
attr_reader :fs
|
|
35
|
-
|
|
36
|
-
attr_reader :inflector
|
|
37
|
-
|
|
38
|
-
def generate_for_slice(context, slice)
|
|
39
|
-
slice_directory = fs.join("slices", slice)
|
|
40
|
-
raise MissingSliceError.new(slice) unless fs.directory?(slice_directory)
|
|
41
|
-
|
|
42
|
-
fs.mkdir(directory = fs.join(slice_directory, context.namespaces))
|
|
43
|
-
fs.write(fs.join(directory, "#{context.underscored_name}.rb"), t("slice_component.erb", context))
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def generate_for_app(context)
|
|
47
|
-
fs.mkdir(directory = fs.join("app", context.namespaces))
|
|
48
|
-
fs.write(fs.join(directory, "#{context.underscored_name}.rb"), t("component.erb", context))
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def template(path, context)
|
|
52
|
-
ERB.new(
|
|
53
|
-
File.read(__dir__ + "/component/#{path}")
|
|
54
|
-
).result(context.ctx)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
alias_method :t, :template
|
|
35
|
+
attr_reader :fs, :inflector, :out
|
|
58
36
|
end
|
|
59
37
|
end
|
|
60
38
|
end
|
|
@@ -20,16 +20,15 @@ module Hanami
|
|
|
20
20
|
# @since 2.2.0
|
|
21
21
|
# @api private
|
|
22
22
|
def call(key:, namespace:, base_path:)
|
|
23
|
-
|
|
23
|
+
RubyClassFile.new(
|
|
24
24
|
fs: fs,
|
|
25
25
|
inflector: inflector,
|
|
26
|
-
|
|
26
|
+
key: key,
|
|
27
27
|
namespace: namespace,
|
|
28
28
|
base_path: base_path,
|
|
29
|
-
|
|
30
|
-
relative_parent_class: "Operation",
|
|
29
|
+
parent_class_name: "#{inflector.camelize(namespace)}::Operation",
|
|
31
30
|
body: ["def call", "end"],
|
|
32
|
-
)
|
|
31
|
+
).create
|
|
33
32
|
|
|
34
33
|
unless key.match?(KEY_SEPARATOR)
|
|
35
34
|
out.puts(
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
require "erb"
|
|
4
4
|
require "dry/files"
|
|
5
|
-
require_relative "../../errors"
|
|
6
5
|
|
|
7
6
|
module Hanami
|
|
8
7
|
module CLI
|
|
@@ -13,87 +12,65 @@ module Hanami
|
|
|
13
12
|
class Part
|
|
14
13
|
# @since 2.1.0
|
|
15
14
|
# @api private
|
|
16
|
-
def initialize(fs:, inflector:)
|
|
15
|
+
def initialize(fs:, inflector:, out: $stdout)
|
|
17
16
|
@fs = fs
|
|
18
17
|
@inflector = inflector
|
|
18
|
+
@out = out
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
# @since 2.1.0
|
|
22
22
|
# @api private
|
|
23
|
-
def call(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
generate_for_slice(context, slice)
|
|
28
|
-
else
|
|
29
|
-
generate_for_app(context)
|
|
30
|
-
end
|
|
23
|
+
def call(key:, namespace:, base_path:, **)
|
|
24
|
+
create_app_base_part_if_missing(key:, namespace:, base_path:)
|
|
25
|
+
create_slice_part_if_missing(key:, namespace:, base_path:) unless namespace == Hanami.app.namespace
|
|
26
|
+
create_generated_part(key:, namespace:, base_path:)
|
|
31
27
|
end
|
|
32
28
|
|
|
33
29
|
private
|
|
34
30
|
|
|
35
31
|
# @since 2.1.0
|
|
36
32
|
# @api private
|
|
37
|
-
attr_reader :fs
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
fs.mkdir(directory = fs.join(slice_directory, "views", "parts", *context.underscored_namespace))
|
|
53
|
-
fs.write(fs.join(directory, "#{context.underscored_name}.rb"), t("slice_part.erb", context))
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# @since 2.1.0
|
|
57
|
-
# @api private
|
|
58
|
-
def generate_for_app(context)
|
|
59
|
-
generate_base_part_for_app(context)
|
|
60
|
-
|
|
61
|
-
fs.mkdir(directory = fs.join("app", "views", "parts", *context.underscored_namespace))
|
|
62
|
-
fs.write(fs.join(directory, "#{context.underscored_name}.rb"), t("app_part.erb", context))
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# @since 2.1.0
|
|
66
|
-
# @api private
|
|
67
|
-
def generate_base_part_for_app(context)
|
|
68
|
-
path = fs.join("app", "views", "part.rb")
|
|
69
|
-
return if fs.exist?(path)
|
|
70
|
-
|
|
71
|
-
fs.write(path, t("app_base_part.erb", context))
|
|
33
|
+
attr_reader :fs, :inflector, :out
|
|
34
|
+
|
|
35
|
+
def create_app_base_part_if_missing(key:, namespace:, base_path:)
|
|
36
|
+
return if fs.exist?(fs.join(base_path, "views", "part.rb"))
|
|
37
|
+
|
|
38
|
+
RubyClassFile.new(
|
|
39
|
+
fs: fs,
|
|
40
|
+
inflector: inflector,
|
|
41
|
+
namespace: Hanami.app.namespace,
|
|
42
|
+
key: "views.part",
|
|
43
|
+
base_path: APP_DIR,
|
|
44
|
+
parent_class_name: "Hanami::View::Part",
|
|
45
|
+
auto_register: false
|
|
46
|
+
).create
|
|
72
47
|
end
|
|
73
48
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
49
|
+
def create_slice_part_if_missing(key:, namespace:, base_path:)
|
|
50
|
+
return if fs.exist?(fs.join(base_path, "views", "part.rb"))
|
|
51
|
+
|
|
52
|
+
RubyClassFile.new(
|
|
53
|
+
fs: fs,
|
|
54
|
+
inflector: inflector,
|
|
55
|
+
namespace: namespace,
|
|
56
|
+
key: "views.part",
|
|
57
|
+
base_path: base_path,
|
|
58
|
+
parent_class_name: "#{Hanami.app.namespace}::Views::Part",
|
|
59
|
+
auto_register: false
|
|
60
|
+
).create
|
|
81
61
|
end
|
|
82
62
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
63
|
+
def create_generated_part(key:, namespace:, base_path:)
|
|
64
|
+
RubyClassFile.new(
|
|
65
|
+
fs: fs,
|
|
66
|
+
inflector: inflector,
|
|
67
|
+
namespace: namespace,
|
|
68
|
+
key: inflector.underscore("views.parts.#{key}"),
|
|
69
|
+
base_path: base_path,
|
|
70
|
+
parent_class_name: "#{inflector.camelize(namespace)}::Views::Part",
|
|
71
|
+
auto_register: false
|
|
72
|
+
).create
|
|
92
73
|
end
|
|
93
|
-
|
|
94
|
-
# @since 2.1.0
|
|
95
|
-
# @api private
|
|
96
|
-
alias_method :t, :template
|
|
97
74
|
end
|
|
98
75
|
end
|
|
99
76
|
end
|
|
@@ -20,22 +20,21 @@ module Hanami
|
|
|
20
20
|
# @since 2.2.0
|
|
21
21
|
# @api private
|
|
22
22
|
def call(key:, namespace:, base_path:, gateway:)
|
|
23
|
-
schema_name = key.split(KEY_SEPARATOR).last
|
|
23
|
+
schema_name = inflector.underscore(key.split(KEY_SEPARATOR).last)
|
|
24
24
|
body_content = ["schema :#{schema_name}, infer: true"]
|
|
25
25
|
|
|
26
26
|
body_content.prepend("gateway :#{gateway}") if gateway
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
RubyClassFile.new(
|
|
29
29
|
fs: fs,
|
|
30
30
|
inflector: inflector,
|
|
31
|
-
).call(
|
|
32
|
-
namespace: namespace,
|
|
33
31
|
key: key,
|
|
32
|
+
namespace: namespace,
|
|
34
33
|
base_path: base_path,
|
|
35
34
|
extra_namespace: "Relations",
|
|
36
|
-
|
|
35
|
+
parent_class_name: "#{inflector.camelize(namespace)}::DB::Relation",
|
|
37
36
|
body: body_content,
|
|
38
|
-
)
|
|
37
|
+
).create
|
|
39
38
|
end
|
|
40
39
|
|
|
41
40
|
private
|
|
@@ -18,17 +18,15 @@ module Hanami
|
|
|
18
18
|
# @since 2.2.0
|
|
19
19
|
# @api private
|
|
20
20
|
def call(key:, namespace:, base_path:)
|
|
21
|
-
|
|
21
|
+
RubyClassFile.new(
|
|
22
22
|
fs: fs,
|
|
23
23
|
inflector: inflector,
|
|
24
|
-
).call(
|
|
25
24
|
key: key,
|
|
26
25
|
namespace: namespace,
|
|
27
26
|
base_path: base_path,
|
|
28
27
|
extra_namespace: "Repos",
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
)
|
|
28
|
+
parent_class_name: "#{inflector.camelize(namespace)}::DB::Repo",
|
|
29
|
+
).create
|
|
32
30
|
end
|
|
33
31
|
|
|
34
32
|
private
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../constants"
|
|
4
|
+
|
|
5
|
+
module Hanami
|
|
6
|
+
module CLI
|
|
7
|
+
module Generators
|
|
8
|
+
module App
|
|
9
|
+
# @api private
|
|
10
|
+
class RubyClassFile < RubyFile
|
|
11
|
+
def initialize(parent_class_name: nil, **args)
|
|
12
|
+
super
|
|
13
|
+
|
|
14
|
+
@parent_class_name = parent_class_name
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
attr_reader :parent_class_name
|
|
20
|
+
|
|
21
|
+
def class_name
|
|
22
|
+
constant_name
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def modules
|
|
26
|
+
namespace_modules
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../constants"
|
|
4
|
+
|
|
5
|
+
module Hanami
|
|
6
|
+
module CLI
|
|
7
|
+
module Generators
|
|
8
|
+
module App
|
|
9
|
+
# @api private
|
|
10
|
+
class RubyFile
|
|
11
|
+
def initialize(
|
|
12
|
+
fs:,
|
|
13
|
+
inflector:,
|
|
14
|
+
key:,
|
|
15
|
+
namespace:,
|
|
16
|
+
base_path:,
|
|
17
|
+
extra_namespace: nil,
|
|
18
|
+
auto_register: nil,
|
|
19
|
+
body: [],
|
|
20
|
+
**_opts
|
|
21
|
+
)
|
|
22
|
+
@fs = fs
|
|
23
|
+
@inflector = inflector
|
|
24
|
+
@key_segments = key.split(KEY_SEPARATOR).map { |segment| inflector.underscore(segment) }
|
|
25
|
+
@namespace = namespace
|
|
26
|
+
@base_path = base_path
|
|
27
|
+
@extra_namespace = extra_namespace&.downcase
|
|
28
|
+
@auto_register = auto_register
|
|
29
|
+
@body = body
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @api private
|
|
33
|
+
def create
|
|
34
|
+
fs.create(path, file_contents)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @api private
|
|
38
|
+
def write
|
|
39
|
+
fs.write(path, file_contents)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @api private
|
|
43
|
+
def fully_qualified_name
|
|
44
|
+
inflector.camelize(
|
|
45
|
+
[namespace, extra_namespace, *key_segments].join("/"),
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @api private
|
|
50
|
+
def path
|
|
51
|
+
fs.join(directory, "#{key_segments.last}.rb")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
# @api private
|
|
57
|
+
attr_reader(
|
|
58
|
+
:fs,
|
|
59
|
+
:inflector,
|
|
60
|
+
:key_segments,
|
|
61
|
+
:base_path,
|
|
62
|
+
:namespace,
|
|
63
|
+
:extra_namespace,
|
|
64
|
+
:auto_register,
|
|
65
|
+
:body,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# @api private
|
|
69
|
+
def file_contents
|
|
70
|
+
RubyFileGenerator.new(
|
|
71
|
+
# These first three must be implemented by subclasses
|
|
72
|
+
class_name: class_name,
|
|
73
|
+
parent_class_name: parent_class_name,
|
|
74
|
+
modules: modules,
|
|
75
|
+
header: headers,
|
|
76
|
+
body: body
|
|
77
|
+
).call
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# @api private
|
|
81
|
+
def local_namespaces
|
|
82
|
+
Array(extra_namespace) + key_segments[..-2]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# @api private
|
|
86
|
+
def namespace_modules
|
|
87
|
+
[namespace, *local_namespaces]
|
|
88
|
+
.map { normalize(_1) }
|
|
89
|
+
.compact
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# @api private
|
|
93
|
+
def directory
|
|
94
|
+
@directory ||= if local_namespaces.any?
|
|
95
|
+
fs.join(base_path, local_namespaces)
|
|
96
|
+
else
|
|
97
|
+
base_path
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# @api private
|
|
102
|
+
def constant_name
|
|
103
|
+
normalize(key_segments.last)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @api private
|
|
107
|
+
def headers
|
|
108
|
+
[
|
|
109
|
+
# Intentional ternary logic. Skip if nil, else 'true' or 'false'
|
|
110
|
+
("# auto_register: #{auto_register}" unless auto_register.nil?),
|
|
111
|
+
"# frozen_string_literal: true",
|
|
112
|
+
].compact
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# @api private
|
|
116
|
+
def normalize(name)
|
|
117
|
+
inflector.camelize(name).gsub(/[^\p{Alnum}]/, "")
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|