hanami-cli 0.3.0 → 2.0.0.alpha3
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 +42 -0
- data/.gitignore +4 -2
- data/.rspec +1 -0
- data/.rubocop.yml +25 -1
- data/CHANGELOG.md +30 -1
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +13 -6
- data/LICENSE.txt +21 -0
- data/README.md +12 -605
- data/Rakefile +9 -12
- data/bin/console +1 -0
- data/exe/hanami +10 -0
- data/hanami-cli.gemspec +25 -18
- data/lib/hanami/cli/bundler.rb +73 -0
- data/lib/hanami/cli/command.rb +16 -355
- data/lib/hanami/cli/command_line.rb +17 -0
- data/lib/hanami/cli/commands/application.rb +63 -0
- data/lib/hanami/cli/commands/db/utils/database.rb +122 -0
- data/lib/hanami/cli/commands/db/utils/database_config.rb +48 -0
- data/lib/hanami/cli/commands/db/utils/mysql.rb +27 -0
- data/lib/hanami/cli/commands/db/utils/postgres.rb +49 -0
- data/lib/hanami/cli/commands/db/utils/sqlite.rb +37 -0
- data/lib/hanami/cli/commands/gem/new.rb +77 -0
- data/lib/hanami/cli/commands/gem/version.rb +18 -0
- data/lib/hanami/cli/commands/gem.rb +21 -0
- data/lib/hanami/cli/commands/monolith/console.rb +50 -0
- data/lib/hanami/cli/commands/monolith/db/create.rb +25 -0
- data/lib/hanami/cli/commands/monolith/db/create_migration.rb +29 -0
- data/lib/hanami/cli/commands/monolith/db/drop.rb +25 -0
- data/lib/hanami/cli/commands/monolith/db/migrate.rb +40 -0
- data/lib/hanami/cli/commands/monolith/db/reset.rb +26 -0
- data/lib/hanami/cli/commands/monolith/db/rollback.rb +55 -0
- data/lib/hanami/cli/commands/monolith/db/sample_data.rb +40 -0
- data/lib/hanami/cli/commands/monolith/db/seed.rb +40 -0
- data/lib/hanami/cli/commands/monolith/db/setup.rb +24 -0
- data/lib/hanami/cli/commands/monolith/db/structure/dump.rb +25 -0
- data/lib/hanami/cli/commands/monolith/db/version.rb +26 -0
- data/lib/hanami/cli/commands/monolith/generate/action.rb +62 -0
- data/lib/hanami/cli/commands/monolith/generate/slice.rb +62 -0
- data/lib/hanami/cli/commands/monolith/generate.rb +14 -0
- data/lib/hanami/cli/commands/monolith/install.rb +16 -0
- data/lib/hanami/cli/commands/monolith/version.rb +18 -0
- data/lib/hanami/cli/commands/monolith.rb +55 -0
- data/lib/hanami/cli/commands.rb +26 -0
- data/lib/hanami/cli/error.rb +8 -0
- data/lib/hanami/cli/generators/context.rb +38 -0
- data/lib/hanami/cli/generators/gem/application/monolith/action.erb +21 -0
- data/lib/hanami/cli/generators/gem/application/monolith/application.erb +8 -0
- data/lib/hanami/cli/generators/gem/application/monolith/config_ru.erb +5 -0
- data/lib/hanami/cli/generators/gem/application/monolith/entities.erb +9 -0
- data/lib/hanami/cli/generators/gem/application/monolith/env.erb +0 -0
- data/lib/hanami/cli/generators/gem/application/monolith/functions.erb +13 -0
- data/lib/hanami/cli/generators/gem/application/monolith/gemfile.erb +19 -0
- data/lib/hanami/cli/generators/gem/application/monolith/keep.erb +0 -0
- data/lib/hanami/cli/generators/gem/application/monolith/operation.erb +18 -0
- data/lib/hanami/cli/generators/gem/application/monolith/rakefile.erb +3 -0
- data/lib/hanami/cli/generators/gem/application/monolith/readme.erb +1 -0
- data/lib/hanami/cli/generators/gem/application/monolith/repository.erb +13 -0
- data/lib/hanami/cli/generators/gem/application/monolith/routes.erb +4 -0
- data/lib/hanami/cli/generators/gem/application/monolith/settings.erb +6 -0
- data/lib/hanami/cli/generators/gem/application/monolith/types.erb +10 -0
- data/lib/hanami/cli/generators/gem/application/monolith/validation_contract.erb +14 -0
- data/lib/hanami/cli/generators/gem/application/monolith/view_context.erb +15 -0
- data/lib/hanami/cli/generators/gem/application/monolith.rb +83 -0
- data/lib/hanami/cli/generators/gem/application.rb +21 -0
- data/lib/hanami/cli/generators/monolith/action/action.erb +13 -0
- data/lib/hanami/cli/generators/monolith/action/template.erb +0 -0
- data/lib/hanami/cli/generators/monolith/action/template.html.erb +2 -0
- data/lib/hanami/cli/generators/monolith/action/view.erb +13 -0
- data/lib/hanami/cli/generators/monolith/action.rb +123 -0
- data/lib/hanami/cli/generators/monolith/action_context.rb +76 -0
- data/lib/hanami/cli/generators/monolith/slice/action.erb +9 -0
- data/lib/hanami/cli/generators/monolith/slice/entities.erb +9 -0
- data/lib/hanami/cli/generators/monolith/slice/keep.erb +0 -0
- data/lib/hanami/cli/generators/monolith/slice/repository.erb +10 -0
- data/lib/hanami/cli/generators/monolith/slice/routes.erb +2 -0
- data/lib/hanami/cli/generators/monolith/slice/view.erb +9 -0
- data/lib/hanami/cli/generators/monolith/slice.rb +56 -0
- data/lib/hanami/cli/generators/monolith/slice_context.rb +33 -0
- data/lib/hanami/cli/repl/core.rb +55 -0
- data/lib/hanami/cli/repl/irb.rb +41 -0
- data/lib/hanami/cli/repl/pry.rb +29 -0
- data/lib/hanami/cli/system_call.rb +51 -0
- data/lib/hanami/cli/url.rb +34 -0
- data/lib/hanami/cli/version.rb +4 -3
- data/lib/hanami/cli.rb +10 -121
- data/lib/hanami/console/context.rb +39 -0
- data/lib/hanami/console/plugins/slice_readers.rb +42 -0
- data/lib/hanami/rake_tasks.rb +52 -0
- metadata +138 -42
- data/.circleci/config.yml +0 -141
- data/.travis.yml +0 -26
- data/lib/hanami/cli/banner.rb +0 -127
- data/lib/hanami/cli/command_registry.rb +0 -213
- data/lib/hanami/cli/errors.rb +0 -44
- data/lib/hanami/cli/option.rb +0 -132
- data/lib/hanami/cli/parser.rb +0 -142
- data/lib/hanami/cli/program_name.rb +0 -19
- data/lib/hanami/cli/registry.rb +0 -328
- data/lib/hanami/cli/usage.rb +0 -89
- data/script/ci +0 -61
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "erb"
|
|
4
|
+
require "shellwords"
|
|
5
|
+
require "hanami/cli/generators/context"
|
|
6
|
+
|
|
7
|
+
module Hanami
|
|
8
|
+
module CLI
|
|
9
|
+
module Generators
|
|
10
|
+
module Gem
|
|
11
|
+
module Application
|
|
12
|
+
class Monolith
|
|
13
|
+
def initialize(fs:, inflector:, command_line:)
|
|
14
|
+
super()
|
|
15
|
+
@fs = fs
|
|
16
|
+
@inflector = inflector
|
|
17
|
+
@command_line = command_line
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def call(app, slice, slice_url_prefix, context: Context.new(inflector, app), &blk)
|
|
21
|
+
generate_app(app, context)
|
|
22
|
+
blk.call
|
|
23
|
+
generate_slice!(slice, slice_url_prefix)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
attr_reader :fs
|
|
29
|
+
|
|
30
|
+
attr_reader :inflector
|
|
31
|
+
|
|
32
|
+
attr_reader :command_line
|
|
33
|
+
|
|
34
|
+
def generate_app(app, context) # rubocop:disable Metrics/AbcSize
|
|
35
|
+
fs.write(".env", t("env.erb", context))
|
|
36
|
+
|
|
37
|
+
fs.write("README.md", t("readme.erb", context))
|
|
38
|
+
fs.write("Gemfile", t("gemfile.erb", context))
|
|
39
|
+
fs.write("Rakefile", t("rakefile.erb", context))
|
|
40
|
+
fs.write("config.ru", t("config_ru.erb", context))
|
|
41
|
+
|
|
42
|
+
fs.write("config/application.rb", t("application.erb", context))
|
|
43
|
+
fs.write("config/settings.rb", t("settings.erb", context))
|
|
44
|
+
fs.write("config/routes.rb", t("routes.erb", context))
|
|
45
|
+
|
|
46
|
+
fs.write("lib/tasks/.keep", t("keep.erb", context))
|
|
47
|
+
|
|
48
|
+
fs.write("lib/#{app}/entities/.keep", t("keep.erb", context))
|
|
49
|
+
fs.write("lib/#{app}/persistence/relations/.keep", t("keep.erb", context))
|
|
50
|
+
fs.write("lib/#{app}/validation/contract.rb", t("validation_contract.erb", context))
|
|
51
|
+
fs.write("lib/#{app}/view/context.rb", t("view_context.erb", context))
|
|
52
|
+
fs.write("lib/#{app}/action.rb", t("action.erb", context))
|
|
53
|
+
fs.write("lib/#{app}/entities.rb", t("entities.erb", context))
|
|
54
|
+
fs.write("lib/#{app}/functions.rb", t("functions.erb", context))
|
|
55
|
+
fs.write("lib/#{app}/operation.rb", t("operation.erb", context))
|
|
56
|
+
fs.write("lib/#{app}/repository.rb", t("repository.erb", context))
|
|
57
|
+
fs.write("lib/#{app}/types.rb", t("types.erb", context))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def generate_slice!(slice_name, slice_url_prefix)
|
|
61
|
+
slice_name = Shellwords.shellescape(slice_name)
|
|
62
|
+
slice_url_prefix = Shellwords.shellescape(slice_url_prefix)
|
|
63
|
+
|
|
64
|
+
command_line.call("hanami generate slice #{slice_name} --url-prefix=#{slice_url_prefix}").tap do |result|
|
|
65
|
+
raise "hanami generate slice #{slice_name} failed\n\n\n#{result.err.inspect}" unless result.successful?
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def template(path, context)
|
|
70
|
+
require "erb"
|
|
71
|
+
|
|
72
|
+
ERB.new(
|
|
73
|
+
File.read(__dir__ + "/monolith/#{path}")
|
|
74
|
+
).result(context.ctx)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
alias_method :t, :template
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanami
|
|
4
|
+
module CLI
|
|
5
|
+
module Generators
|
|
6
|
+
module Gem
|
|
7
|
+
module Application
|
|
8
|
+
class << self
|
|
9
|
+
def call(architecture, fs, inflector, command_line)
|
|
10
|
+
require_relative "./application/#{architecture}"
|
|
11
|
+
|
|
12
|
+
generator_name = inflector.classify(architecture).to_sym
|
|
13
|
+
const_get(generator_name).new(fs: fs, inflector: inflector, command_line: command_line)
|
|
14
|
+
end
|
|
15
|
+
alias_method :[], :call
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# auto_register: false
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "<%= underscored_slice_name %>/action"
|
|
5
|
+
|
|
6
|
+
module <%= classified_slice_name %>
|
|
7
|
+
module Actions
|
|
8
|
+
<%= module_controller_declaration %>
|
|
9
|
+
<%= module_controller_offset %>class <%= classified_action_name %> < <%= classified_slice_name %>::Action
|
|
10
|
+
<%= module_controller_offset %>end
|
|
11
|
+
<%= module_controller_end %>
|
|
12
|
+
end
|
|
13
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# auto_register: false
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "<%= underscored_slice_name %>/view"
|
|
5
|
+
|
|
6
|
+
module <%= classified_slice_name %>
|
|
7
|
+
module Views
|
|
8
|
+
<%= module_controller_declaration %>
|
|
9
|
+
<%= module_controller_offset %>class <%= classified_action_name %> < <%= classified_slice_name %>::View
|
|
10
|
+
<%= module_controller_offset %>end
|
|
11
|
+
<%= module_controller_end %>
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "erb"
|
|
4
|
+
require "dry/files"
|
|
5
|
+
require "hanami/cli/generators/monolith/action_context"
|
|
6
|
+
require "hanami/cli/url"
|
|
7
|
+
|
|
8
|
+
module Hanami
|
|
9
|
+
module CLI
|
|
10
|
+
module Generators
|
|
11
|
+
module Monolith
|
|
12
|
+
class Action
|
|
13
|
+
def initialize(fs:, inflector:)
|
|
14
|
+
@fs = fs
|
|
15
|
+
@inflector = inflector
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# rubocop:disable Metrics/AbcSize
|
|
19
|
+
# rubocop:disable Metrics/ParameterLists
|
|
20
|
+
# rubocop:disable Layout/LineLength
|
|
21
|
+
def call(slice, controller, action, url, http, format, skip_view, context: ActionContext.new(inflector, slice, controller, action))
|
|
22
|
+
slice_directory = fs.join("slices", slice)
|
|
23
|
+
raise ArgumentError.new("slice not found `#{slice}'") unless fs.directory?(slice_directory)
|
|
24
|
+
|
|
25
|
+
fs.inject_line_at_block_bottom(
|
|
26
|
+
fs.join("config", "routes.rb"),
|
|
27
|
+
slice_matcher(slice),
|
|
28
|
+
route(controller, action, url, http)
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
fs.chdir(slice_directory) do
|
|
32
|
+
fs.mkdir(directory = fs.join("actions", controller))
|
|
33
|
+
fs.write(fs.join(directory, "#{action}.rb"), t("action.erb", context))
|
|
34
|
+
|
|
35
|
+
unless skip_view
|
|
36
|
+
fs.mkdir(directory = fs.join("views", controller))
|
|
37
|
+
fs.write(fs.join(directory, "#{action}.rb"), t("view.erb", context))
|
|
38
|
+
|
|
39
|
+
fs.mkdir(directory = fs.join("templates", controller))
|
|
40
|
+
fs.write(fs.join(directory, "#{action}.#{format}.erb"), t(template_format(format), context))
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
# rubocop:enable Layout/LineLength
|
|
45
|
+
# rubocop:enable Metrics/ParameterLists
|
|
46
|
+
# rubocop:enable Metrics/AbcSize
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
ROUTE_HTTP_METHODS = %w[get post delete put patch trace options link unlink].freeze
|
|
51
|
+
private_constant :ROUTE_HTTP_METHODS
|
|
52
|
+
|
|
53
|
+
ROUTE_DEFAULT_HTTP_METHOD = "get"
|
|
54
|
+
private_constant :ROUTE_DEFAULT_HTTP_METHOD
|
|
55
|
+
|
|
56
|
+
ROUTE_RESTFUL_HTTP_METHODS = {
|
|
57
|
+
"create" => "post",
|
|
58
|
+
"update" => "patch",
|
|
59
|
+
"destroy" => "delete"
|
|
60
|
+
}.freeze
|
|
61
|
+
private_constant :ROUTE_RESTFUL_HTTP_METHODS
|
|
62
|
+
|
|
63
|
+
ROUTE_RESTFUL_URL_SUFFIXES = {
|
|
64
|
+
"index" => "",
|
|
65
|
+
"new" => "/new",
|
|
66
|
+
"create" => "",
|
|
67
|
+
"edit" => "/:id/edit",
|
|
68
|
+
"update" => "/:id",
|
|
69
|
+
"show" => "/:id",
|
|
70
|
+
"destroy" => "/:id"
|
|
71
|
+
}.freeze
|
|
72
|
+
private_constant :ROUTE_RESTFUL_URL_SUFFIXES
|
|
73
|
+
|
|
74
|
+
attr_reader :fs
|
|
75
|
+
|
|
76
|
+
attr_reader :inflector
|
|
77
|
+
|
|
78
|
+
def slice_matcher(slice)
|
|
79
|
+
/slice[[:space:]]*:#{slice}/
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def route(controller, action, url, http)
|
|
83
|
+
%(#{route_http(action,
|
|
84
|
+
http)} "#{route_url(controller, action, url)}", to: "#{controller.join('.')}.#{action}")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def template_format(format)
|
|
88
|
+
case format.to_sym
|
|
89
|
+
when :html
|
|
90
|
+
"template.html.erb"
|
|
91
|
+
else
|
|
92
|
+
"template.erb"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def template(path, context)
|
|
97
|
+
require "erb"
|
|
98
|
+
|
|
99
|
+
ERB.new(
|
|
100
|
+
File.read(__dir__ + "/action/#{path}")
|
|
101
|
+
).result(context.ctx)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
alias_method :t, :template
|
|
105
|
+
|
|
106
|
+
def route_url(controller, action, url)
|
|
107
|
+
CLI::URL.call(url || "/#{controller.join('/')}" + ROUTE_RESTFUL_URL_SUFFIXES.fetch(action))
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def route_http(action, http)
|
|
111
|
+
result = (http ||= ROUTE_RESTFUL_HTTP_METHODS.fetch(action, ROUTE_DEFAULT_HTTP_METHOD)).downcase
|
|
112
|
+
|
|
113
|
+
unless ROUTE_HTTP_METHODS.include?(result)
|
|
114
|
+
raise ArgumentError.new("unknown HTTP method: `#{http}'")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
result
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "./slice_context"
|
|
4
|
+
require "dry/files/path"
|
|
5
|
+
|
|
6
|
+
module Hanami
|
|
7
|
+
module CLI
|
|
8
|
+
module Generators
|
|
9
|
+
module Monolith
|
|
10
|
+
class ActionContext < SliceContext
|
|
11
|
+
def initialize(inflector, slice, controller, action)
|
|
12
|
+
@controller = controller
|
|
13
|
+
@action = action
|
|
14
|
+
super(inflector, nil, slice, nil)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def classified_controller_name
|
|
18
|
+
controller.map do |token|
|
|
19
|
+
inflector.camelize(token)
|
|
20
|
+
end.join(NAMESPACE_SEPARATOR)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def classified_action_name
|
|
24
|
+
inflector.classify(action)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def underscored_controller_name
|
|
28
|
+
controller.map do |token|
|
|
29
|
+
inflector.underscore(token)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def underscored_action_name
|
|
34
|
+
inflector.underscore(action)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def module_controller_declaration
|
|
38
|
+
controller.each_with_index.map do |token, i|
|
|
39
|
+
"#{OFFSET}#{INDENTATION * i}module #{inflector.camelize(token)}"
|
|
40
|
+
end.join($/)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def module_controller_end
|
|
44
|
+
controller.each_with_index.map do |_, i|
|
|
45
|
+
"#{OFFSET}#{INDENTATION * i}end"
|
|
46
|
+
end.reverse.join($/)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def module_controller_offset
|
|
50
|
+
"#{OFFSET}#{INDENTATION * controller.count}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def template_path
|
|
54
|
+
Dry::Files::Path["slices", underscored_slice_name, "templates", *underscored_controller_name,
|
|
55
|
+
"#{underscored_action_name}.html.erb"]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
NAMESPACE_SEPARATOR = "::"
|
|
61
|
+
private_constant :NAMESPACE_SEPARATOR
|
|
62
|
+
|
|
63
|
+
INDENTATION = " "
|
|
64
|
+
private_constant :INDENTATION
|
|
65
|
+
|
|
66
|
+
OFFSET = INDENTATION * 2
|
|
67
|
+
private_constant :OFFSET
|
|
68
|
+
|
|
69
|
+
attr_reader :controller
|
|
70
|
+
|
|
71
|
+
attr_reader :action
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "erb"
|
|
4
|
+
require "dry/files"
|
|
5
|
+
require "hanami/cli/generators/monolith/slice_context"
|
|
6
|
+
|
|
7
|
+
module Hanami
|
|
8
|
+
module CLI
|
|
9
|
+
module Generators
|
|
10
|
+
module Monolith
|
|
11
|
+
class Slice
|
|
12
|
+
def initialize(fs:, inflector:)
|
|
13
|
+
@fs = fs
|
|
14
|
+
@inflector = inflector
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call(app, slice, slice_url_prefix, context: SliceContext.new(inflector, app, slice, slice_url_prefix)) # rubocop:disable Metrics/AbcSize
|
|
18
|
+
fs.inject_line_before_last(fs.join("config", "routes.rb"), /end/, t("routes.erb", context).chomp)
|
|
19
|
+
|
|
20
|
+
fs.mkdir(directory = "slices/#{slice}")
|
|
21
|
+
|
|
22
|
+
fs.chdir(directory) do
|
|
23
|
+
fs.write("action.rb", t("action.erb", context))
|
|
24
|
+
fs.write("view.rb", t("view.erb", context))
|
|
25
|
+
fs.write("entities.rb", t("entities.erb", context))
|
|
26
|
+
fs.write("repository.rb", t("repository.erb", context))
|
|
27
|
+
|
|
28
|
+
fs.write("actions/.keep", t("keep.erb", context))
|
|
29
|
+
fs.write("views/.keep", t("keep.erb", context))
|
|
30
|
+
fs.write("templates/.keep", t("keep.erb", context))
|
|
31
|
+
fs.write("templates/layouts/.keep", t("keep.erb", context))
|
|
32
|
+
fs.write("entities/.keep", t("keep.erb", context))
|
|
33
|
+
fs.write("repositories/.keep", t("keep.erb", context))
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
attr_reader :fs
|
|
40
|
+
|
|
41
|
+
attr_reader :inflector
|
|
42
|
+
|
|
43
|
+
def template(path, context)
|
|
44
|
+
require "erb"
|
|
45
|
+
|
|
46
|
+
ERB.new(
|
|
47
|
+
File.read(__dir__ + "/slice/#{path}")
|
|
48
|
+
).result(context.ctx)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
alias_method :t, :template
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../context"
|
|
4
|
+
|
|
5
|
+
module Hanami
|
|
6
|
+
module CLI
|
|
7
|
+
module Generators
|
|
8
|
+
module Monolith
|
|
9
|
+
class SliceContext < Generators::Context
|
|
10
|
+
def initialize(inflector, app, slice, slice_url_prefix)
|
|
11
|
+
@slice = slice
|
|
12
|
+
@slice_url_prefix = slice_url_prefix
|
|
13
|
+
super(inflector, app)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def classified_slice_name
|
|
17
|
+
inflector.classify(slice)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def underscored_slice_name
|
|
21
|
+
inflector.underscore(slice)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
attr_reader :slice
|
|
27
|
+
|
|
28
|
+
attr_reader :slice_url_prefix
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "hanami/console/context"
|
|
4
|
+
|
|
5
|
+
module Hanami
|
|
6
|
+
module CLI
|
|
7
|
+
module Repl
|
|
8
|
+
# @api private
|
|
9
|
+
class Core
|
|
10
|
+
# @api private
|
|
11
|
+
attr_reader :application
|
|
12
|
+
|
|
13
|
+
# @api private
|
|
14
|
+
attr_reader :opts
|
|
15
|
+
|
|
16
|
+
# @api private
|
|
17
|
+
def initialize(application, opts)
|
|
18
|
+
@application = application
|
|
19
|
+
@opts = opts
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @api private
|
|
23
|
+
def start
|
|
24
|
+
raise NotImplementedError
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @api private
|
|
28
|
+
def context
|
|
29
|
+
@context ||= Hanami::Console::Context.new(application)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @api private
|
|
33
|
+
def prompt
|
|
34
|
+
"#{name}[#{env}]"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @api private
|
|
38
|
+
def name
|
|
39
|
+
(application.container.config.name || inflector.underscore(application.name))
|
|
40
|
+
.split("/")[0]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @api private
|
|
44
|
+
def env
|
|
45
|
+
application.container.env
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @api private
|
|
49
|
+
def inflector
|
|
50
|
+
application.inflector
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "irb"
|
|
4
|
+
require_relative "core"
|
|
5
|
+
|
|
6
|
+
module Hanami
|
|
7
|
+
module CLI
|
|
8
|
+
module Repl
|
|
9
|
+
# @since 2.0.0
|
|
10
|
+
# @api public
|
|
11
|
+
class Irb < Core
|
|
12
|
+
# @api public
|
|
13
|
+
def start
|
|
14
|
+
ARGV.shift until ARGV.empty?
|
|
15
|
+
TOPLEVEL_BINDING.eval('self').extend(context)
|
|
16
|
+
|
|
17
|
+
IRB.conf[:PROMPT] = {}
|
|
18
|
+
|
|
19
|
+
IRB.conf[:PROMPT][:MY_PROMPT] = {
|
|
20
|
+
:AUTO_INDENT => true,
|
|
21
|
+
:PROMPT_I => ">> ",
|
|
22
|
+
:PROMPT_S => nil,
|
|
23
|
+
:PROMPT_C => nil,
|
|
24
|
+
:RETURN => " ==>%s\n"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
IRB.conf[:PROMPT_MODE] = :MY_PROMPT
|
|
28
|
+
|
|
29
|
+
IRB.start
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
# @api private
|
|
35
|
+
def conf
|
|
36
|
+
@conf ||= IRB.conf
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "pry"
|
|
4
|
+
require_relative "core"
|
|
5
|
+
|
|
6
|
+
module Hanami
|
|
7
|
+
module CLI
|
|
8
|
+
module Repl
|
|
9
|
+
# @since 2.0.0
|
|
10
|
+
# @api public
|
|
11
|
+
class Pry < Core
|
|
12
|
+
# @api private
|
|
13
|
+
class Context
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @api public
|
|
17
|
+
def start
|
|
18
|
+
::Pry.config.prompt = ::Pry::Prompt.new(
|
|
19
|
+
"hanami",
|
|
20
|
+
"my custom prompt",
|
|
21
|
+
[proc { |*| "#{prompt}> " }]
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
::Pry.start(Context.new.extend(context))
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanami
|
|
4
|
+
module CLI
|
|
5
|
+
class SystemCall
|
|
6
|
+
class Result
|
|
7
|
+
SUCCESSFUL_EXIT_CODE = 0
|
|
8
|
+
private_constant :SUCCESSFUL_EXIT_CODE
|
|
9
|
+
|
|
10
|
+
attr_reader :exit_code, :out, :err
|
|
11
|
+
|
|
12
|
+
def initialize(exit_code:, out:, err:)
|
|
13
|
+
@exit_code = exit_code
|
|
14
|
+
@out = out
|
|
15
|
+
@err = err
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def successful?
|
|
19
|
+
exit_code == SUCCESSFUL_EXIT_CODE
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Adapted from Bundler source code
|
|
24
|
+
#
|
|
25
|
+
# Bundler is released under MIT license
|
|
26
|
+
# https://github.com/bundler/bundler/blob/master/LICENSE.md
|
|
27
|
+
#
|
|
28
|
+
# A special "thank you" goes to Bundler maintainers and contributors.
|
|
29
|
+
#
|
|
30
|
+
# Also adapted from `hanami-devtools` source code
|
|
31
|
+
def call(cmd, env: {})
|
|
32
|
+
exitstatus = nil
|
|
33
|
+
out = nil
|
|
34
|
+
err = nil
|
|
35
|
+
|
|
36
|
+
::Bundler.with_unbundled_env do
|
|
37
|
+
Open3.popen3(env, cmd) do |stdin, stdout, stderr, wait_thr|
|
|
38
|
+
yield stdin, stdout, wait_thr if block_given?
|
|
39
|
+
stdin.close
|
|
40
|
+
|
|
41
|
+
exitstatus = wait_thr&.value&.exitstatus
|
|
42
|
+
out = Thread.new { stdout.read }.value.strip
|
|
43
|
+
err = Thread.new { stderr.read }.value.strip
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
Result.new(exit_code: exitstatus, out: out, err: err)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|