hanami-cli 1.0.0.alpha1 → 2.0.0.alpha6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +50 -0
- data/.gitignore +4 -2
- data/.rspec +1 -0
- data/.rubocop.yml +28 -1
- data/CHANGELOG.md +32 -1
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +9 -2
- data/LICENSE.txt +21 -0
- data/README.md +12 -605
- data/Rakefile +5 -10
- data/exe/hanami +10 -0
- data/hanami-cli.gemspec +22 -17
- data/lib/hanami/cli/bundler.rb +73 -0
- data/lib/hanami/cli/command.rb +14 -386
- 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 +49 -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 +38 -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 +2 -3
- data/lib/hanami/cli.rb +9 -122
- data/lib/hanami/console/context.rb +53 -0
- data/lib/hanami/console/plugins/slice_readers.rb +24 -0
- data/lib/hanami/rake_tasks.rb +52 -0
- metadata +135 -43
- data/.circleci/config.yml +0 -63
- data/.travis.yml +0 -22
- data/lib/hanami/cli/banner.rb +0 -129
- data/lib/hanami/cli/command_registry.rb +0 -215
- data/lib/hanami/cli/errors.rb +0 -46
- data/lib/hanami/cli/option.rb +0 -134
- data/lib/hanami/cli/parser.rb +0 -144
- data/lib/hanami/cli/program_name.rb +0 -21
- data/lib/hanami/cli/registry.rb +0 -330
- data/lib/hanami/cli/usage.rb +0 -91
- 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
|
+
.to_s.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,38 @@
|
|
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
|
+
$stdout.sync = true
|
15
|
+
|
16
|
+
ARGV.shift until ARGV.empty?
|
17
|
+
TOPLEVEL_BINDING.eval("self").extend(context)
|
18
|
+
|
19
|
+
# Initializes the IRB.conf; our own conf changes must be after this
|
20
|
+
IRB.setup(nil)
|
21
|
+
|
22
|
+
IRB.conf[:PROMPT][:HANAMI] = {
|
23
|
+
AUTO_INDENT: true,
|
24
|
+
PROMPT_I: "#{prompt}> ",
|
25
|
+
PROMPT_N: "#{prompt}> ",
|
26
|
+
PROMPT_S: "#{prompt} %l> ",
|
27
|
+
PROMPT_C: "#{prompt} ?> ",
|
28
|
+
RETURN: "=> %s\n"
|
29
|
+
}
|
30
|
+
|
31
|
+
IRB.conf[:PROMPT_MODE] = :HANAMI
|
32
|
+
|
33
|
+
IRB::Irb.new.run
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
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
|