hanami-cli 1.0.0.alpha1 → 2.0.0.alpha2
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 +24 -0
- data/CHANGELOG.md +14 -1
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +8 -2
- data/LICENSE.txt +21 -0
- data/README.md +12 -605
- data/Rakefile +5 -10
- data/exe/hanami +10 -0
- data/hanami-cli.gemspec +21 -17
- data/lib/hanami/cli.rb +9 -122
- 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.rb +26 -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.rb +21 -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/monolith.rb +55 -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.rb +14 -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/install.rb +16 -0
- data/lib/hanami/cli/commands/monolith/version.rb +18 -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.rb +21 -0
- data/lib/hanami/cli/generators/gem/application/monolith.rb +83 -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/monolith/action.rb +123 -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_context.rb +76 -0
- data/lib/hanami/cli/generators/monolith/slice.rb +56 -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_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 +2 -3
- 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 +134 -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
data/Rakefile
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "rake"
|
|
4
3
|
require "bundler/gem_tasks"
|
|
5
4
|
require "rspec/core/rake_task"
|
|
6
|
-
require "hanami/devtools/rake_tasks"
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
RSpec::Core::RakeTask.new(:unit) do |task|
|
|
10
|
-
file_list = FileList["spec/**/*_spec.rb"]
|
|
11
|
-
file_list = file_list.exclude("spec/{integration,isolation}/**/*_spec.rb")
|
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
12
7
|
|
|
13
|
-
|
|
14
|
-
end
|
|
15
|
-
end
|
|
8
|
+
require "rubocop/rake_task"
|
|
16
9
|
|
|
17
|
-
|
|
10
|
+
RuboCop::RakeTask.new
|
|
11
|
+
|
|
12
|
+
task default: %i[spec rubocop]
|
data/exe/hanami
ADDED
data/hanami-cli.gemspec
CHANGED
|
@@ -1,36 +1,40 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
-
require "hanami/cli/version"
|
|
3
|
+
require_relative "lib/hanami/cli/version"
|
|
6
4
|
|
|
7
5
|
Gem::Specification.new do |spec|
|
|
8
6
|
spec.name = "hanami-cli"
|
|
9
7
|
spec.version = Hanami::CLI::VERSION
|
|
10
8
|
spec.authors = ["Luca Guidi"]
|
|
11
9
|
spec.email = ["me@lucaguidi.com"]
|
|
12
|
-
spec.licenses = ["MIT"]
|
|
13
10
|
|
|
14
11
|
spec.summary = "Hanami CLI"
|
|
15
|
-
spec.description = "Hanami
|
|
16
|
-
spec.homepage = "
|
|
12
|
+
spec.description = "Hanami command line"
|
|
13
|
+
spec.homepage = "https://hanamirb.org"
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
|
|
17
16
|
|
|
18
17
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
|
18
|
+
|
|
19
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
19
20
|
spec.metadata["source_code_uri"] = "https://github.com/hanami/cli"
|
|
21
|
+
spec.metadata["changelog_uri"] = "https://github.com/hanami/cli/blob/master/CHANGELOG.md"
|
|
20
22
|
|
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
25
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
26
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
|
27
|
+
end
|
|
21
28
|
spec.bindir = "exe"
|
|
22
|
-
spec.executables = spec.files.grep(%r{
|
|
29
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
23
30
|
spec.require_paths = ["lib"]
|
|
24
|
-
spec.required_ruby_version = ">= 2.5.0"
|
|
25
|
-
|
|
26
|
-
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
27
|
-
f.match(%r{^(test|spec|features)/})
|
|
28
|
-
end
|
|
29
31
|
|
|
30
|
-
spec.add_dependency "
|
|
31
|
-
spec.add_dependency "
|
|
32
|
+
spec.add_dependency "bundler", "~> 2.1"
|
|
33
|
+
spec.add_dependency "rake", "~> 13.0"
|
|
34
|
+
spec.add_dependency "dry-cli", "~> 0.6"
|
|
35
|
+
spec.add_dependency "dry-files", "~> 0.1"
|
|
36
|
+
spec.add_dependency "dry-inflector", "~> 0.2"
|
|
32
37
|
|
|
33
|
-
spec.add_development_dependency "
|
|
34
|
-
spec.add_development_dependency "
|
|
35
|
-
spec.add_development_dependency "rspec", "~> 3.7"
|
|
38
|
+
spec.add_development_dependency "rspec", "~> 3.9"
|
|
39
|
+
spec.add_development_dependency "rubocop", "~> 1.11"
|
|
36
40
|
end
|
data/lib/hanami/cli.rb
CHANGED
|
@@ -1,129 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
# @since 0.1.0
|
|
6
|
-
module Hanami
|
|
7
|
-
# General purpose Command Line Interface (CLI) framework for Ruby
|
|
8
|
-
#
|
|
9
|
-
# @since 0.1.0
|
|
10
|
-
class CLI
|
|
11
|
-
require "hanami/cli/version"
|
|
12
|
-
require "hanami/cli/errors"
|
|
13
|
-
require "hanami/cli/command"
|
|
14
|
-
require "hanami/cli/registry"
|
|
15
|
-
require "hanami/cli/parser"
|
|
16
|
-
require "hanami/cli/usage"
|
|
17
|
-
require "hanami/cli/banner"
|
|
18
|
-
|
|
19
|
-
# Check if command
|
|
20
|
-
#
|
|
21
|
-
# @param command [Object] the command to check
|
|
22
|
-
#
|
|
23
|
-
# @return [TrueClass,FalseClass] true if instance of `Hanami::CLI::Command`
|
|
24
|
-
#
|
|
25
|
-
# @since 0.1.0
|
|
26
|
-
# @api private
|
|
27
|
-
def self.command?(command)
|
|
28
|
-
case command
|
|
29
|
-
when Class
|
|
30
|
-
command.ancestors.include?(Command)
|
|
31
|
-
else
|
|
32
|
-
command.is_a?(Command)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Create a new instance
|
|
37
|
-
#
|
|
38
|
-
# @param registry [Hanami::CLI::Registry] a registry
|
|
39
|
-
#
|
|
40
|
-
# @return [Hanami::CLI] the new instance
|
|
41
|
-
# @since 0.1.0
|
|
42
|
-
def initialize(registry)
|
|
43
|
-
@commands = registry
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# Invoke the CLI
|
|
47
|
-
#
|
|
48
|
-
# @param arguments [Array<string>] the command line arguments (defaults to `ARGV`)
|
|
49
|
-
# @param out [IO] the standard output (defaults to `$stdout`)
|
|
50
|
-
#
|
|
51
|
-
# @since 0.1.0
|
|
52
|
-
def call(arguments: ARGV, out: $stdout)
|
|
53
|
-
result = commands.get(arguments)
|
|
54
|
-
|
|
55
|
-
if result.found?
|
|
56
|
-
command, args = parse(result, out)
|
|
57
|
-
|
|
58
|
-
result.before_callbacks.run(command, args)
|
|
59
|
-
command.call(args)
|
|
60
|
-
result.after_callbacks.run(command, args)
|
|
61
|
-
else
|
|
62
|
-
usage(result, out)
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
private
|
|
3
|
+
require "dry/cli"
|
|
67
4
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
# It may exit in case of error, or in case of help.
|
|
75
|
-
#
|
|
76
|
-
# @param result [Hanami::CLI::CommandRegistry::LookupResult]
|
|
77
|
-
# @param out [IO] sta output
|
|
78
|
-
#
|
|
79
|
-
# @return [Array<Hanami:CLI::Command, Array>] returns an array where the
|
|
80
|
-
# first element is a command and the second one is the list of arguments
|
|
81
|
-
#
|
|
82
|
-
# @since 0.1.0
|
|
83
|
-
# @api private
|
|
84
|
-
def parse(result, out) # rubocop:disable Metrics/MethodLength
|
|
85
|
-
command = result.command
|
|
86
|
-
return [command, result.arguments] unless command?(command)
|
|
87
|
-
|
|
88
|
-
result = Parser.call(command, result.arguments, result.names)
|
|
89
|
-
|
|
90
|
-
if result.help?
|
|
91
|
-
Banner.call(command, out)
|
|
92
|
-
exit(0)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
if result.error?
|
|
96
|
-
out.puts(result.error)
|
|
97
|
-
exit(1)
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
[command, result.arguments]
|
|
101
|
-
end
|
|
5
|
+
module Hanami
|
|
6
|
+
module CLI
|
|
7
|
+
require_relative "cli/version"
|
|
8
|
+
require_relative "cli/error"
|
|
9
|
+
require_relative "cli/bundler"
|
|
10
|
+
require_relative "cli/commands"
|
|
102
11
|
|
|
103
|
-
|
|
104
|
-
#
|
|
105
|
-
# @param result [Hanami::CLI::CommandRegistry::LookupResult]
|
|
106
|
-
# @param out [IO] sta output
|
|
107
|
-
#
|
|
108
|
-
# @since 0.1.0
|
|
109
|
-
# @api private
|
|
110
|
-
def usage(result, out)
|
|
111
|
-
Usage.call(result, out)
|
|
112
|
-
exit(1)
|
|
113
|
-
end
|
|
12
|
+
extend Dry::CLI::Registry
|
|
114
13
|
|
|
115
|
-
|
|
116
|
-
#
|
|
117
|
-
# @param command [Object] the command to check
|
|
118
|
-
#
|
|
119
|
-
# @return [TrueClass,FalseClass] true if instance of `Hanami::CLI::Command`
|
|
120
|
-
#
|
|
121
|
-
# @since 0.1.0
|
|
122
|
-
# @api private
|
|
123
|
-
#
|
|
124
|
-
# @see .command?
|
|
125
|
-
def command?(command)
|
|
126
|
-
CLI.command?(command)
|
|
127
|
-
end
|
|
14
|
+
register_commands!
|
|
128
15
|
end
|
|
129
16
|
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler"
|
|
4
|
+
require "open3"
|
|
5
|
+
require "etc"
|
|
6
|
+
require "dry/files"
|
|
7
|
+
require_relative "./system_call"
|
|
8
|
+
|
|
9
|
+
module Hanami
|
|
10
|
+
module CLI
|
|
11
|
+
class Bundler
|
|
12
|
+
BUNDLE_GEMFILE = "BUNDLE_GEMFILE"
|
|
13
|
+
private_constant :BUNDLE_GEMFILE
|
|
14
|
+
|
|
15
|
+
DEFAULT_GEMFILE_PATH = "Gemfile"
|
|
16
|
+
private_constant :DEFAULT_GEMFILE_PATH
|
|
17
|
+
|
|
18
|
+
def self.require(*groups)
|
|
19
|
+
return unless File.exist?(ENV[BUNDLE_GEMFILE] || DEFAULT_GEMFILE_PATH)
|
|
20
|
+
|
|
21
|
+
::Bundler.require(*groups)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def initialize(fs: Dry::Files.new, system_call: SystemCall.new)
|
|
25
|
+
@fs = fs
|
|
26
|
+
@system_call = system_call
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def install
|
|
30
|
+
parallelism_level = Etc.nprocessors
|
|
31
|
+
bundle "install --jobs=#{parallelism_level} --quiet --no-color"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def install!
|
|
35
|
+
install.tap do |result|
|
|
36
|
+
raise "Bundle install failed\n\n\n#{result.err.inspect}" unless result.successful?
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def exec(cmd, env: nil, &blk)
|
|
41
|
+
bundle("exec #{cmd}", env: env, &blk)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def bundle(cmd, env: nil, &blk)
|
|
45
|
+
bundle_bin = which("bundle")
|
|
46
|
+
hanami_env = "HANAMI_ENV=#{env} " unless env.nil?
|
|
47
|
+
|
|
48
|
+
system_call.call("#{hanami_env}#{bundle_bin} #{cmd}",
|
|
49
|
+
env: {BUNDLE_GEMFILE => fs.expand_path(DEFAULT_GEMFILE_PATH)}, &blk)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
attr_reader :fs
|
|
55
|
+
|
|
56
|
+
attr_reader :system_call
|
|
57
|
+
|
|
58
|
+
# Adapted from https://stackoverflow.com/a/5471032/498386
|
|
59
|
+
def which(cmd)
|
|
60
|
+
exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
|
|
61
|
+
|
|
62
|
+
ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
|
|
63
|
+
exts.each do |ext|
|
|
64
|
+
exe = fs.join(path, "#{cmd}#{ext}")
|
|
65
|
+
return exe if fs.executable?(exe) && !fs.directory?(exe)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
nil
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/hanami/cli/command.rb
CHANGED
|
@@ -1,398 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
4
|
-
require "
|
|
5
|
-
require "
|
|
6
|
-
require "hanami/utils/class_attribute"
|
|
3
|
+
require "dry/cli"
|
|
4
|
+
require "dry/files"
|
|
5
|
+
require "dry/inflector"
|
|
7
6
|
|
|
8
7
|
module Hanami
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def self.inherited(base)
|
|
17
|
-
super
|
|
18
|
-
base.extend ClassMethods
|
|
8
|
+
module CLI
|
|
9
|
+
class Command < Dry::CLI::Command
|
|
10
|
+
def initialize(out: $stdout, fs: Dry::Files.new, inflector: Dry::Inflector.new)
|
|
11
|
+
super()
|
|
12
|
+
@out = out
|
|
13
|
+
@fs = fs
|
|
14
|
+
@inflector = inflector
|
|
19
15
|
end
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
# @api private
|
|
23
|
-
module ClassMethods
|
|
24
|
-
# @since 0.1.0
|
|
25
|
-
# @api private
|
|
26
|
-
#
|
|
27
|
-
# rubocop:disable Metrics/MethodLength
|
|
28
|
-
def self.extended(base)
|
|
29
|
-
super
|
|
30
|
-
return unless extend?(base)
|
|
17
|
+
private
|
|
31
18
|
|
|
32
|
-
|
|
33
|
-
include Utils::ClassAttribute
|
|
19
|
+
attr_reader :out
|
|
34
20
|
|
|
35
|
-
|
|
36
|
-
self.description = nil
|
|
21
|
+
attr_reader :fs
|
|
37
22
|
|
|
38
|
-
|
|
39
|
-
self.examples = Concurrent::Array.new
|
|
40
|
-
|
|
41
|
-
class_attribute :arguments
|
|
42
|
-
self.arguments = Concurrent::Array.new
|
|
43
|
-
|
|
44
|
-
class_attribute :options
|
|
45
|
-
self.options = Concurrent::Array.new
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
# rubocop:enable Metrics/MethodLength
|
|
49
|
-
|
|
50
|
-
# Only add class attributes if a command is inheriting directly from `Hanami::CLI::Command`.
|
|
51
|
-
# In this way, its subclasses can inherit arguments/options from the parent class.
|
|
52
|
-
#
|
|
53
|
-
# @return [TrueClass,FalseClass] the result of the check
|
|
54
|
-
#
|
|
55
|
-
# @since 1.0.0
|
|
56
|
-
# @api private
|
|
57
|
-
#
|
|
58
|
-
# @example
|
|
59
|
-
# # For this class `extend?` will return `true`
|
|
60
|
-
# class Server < Hanami::CLI::Command
|
|
61
|
-
# option :engine
|
|
62
|
-
#
|
|
63
|
-
# def call(**options)
|
|
64
|
-
# # start the server
|
|
65
|
-
# end
|
|
66
|
-
# end
|
|
67
|
-
#
|
|
68
|
-
# # For this class `extend?` will return `false`
|
|
69
|
-
# class ServerReloader < Server
|
|
70
|
-
# option :reload, type: :boolean, default: true
|
|
71
|
-
#
|
|
72
|
-
# def call(**options)
|
|
73
|
-
# reload = options.fetch(:reload)
|
|
74
|
-
# super unless reload
|
|
75
|
-
#
|
|
76
|
-
# # activate reloading
|
|
77
|
-
# end
|
|
78
|
-
# end
|
|
79
|
-
def self.extend?(base)
|
|
80
|
-
base.superclass == Hanami::CLI::Command
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Set the description of the command
|
|
85
|
-
#
|
|
86
|
-
# @param description [String] the description
|
|
87
|
-
#
|
|
88
|
-
# @since 0.1.0
|
|
89
|
-
#
|
|
90
|
-
# @example
|
|
91
|
-
# require "hanami/cli"
|
|
92
|
-
#
|
|
93
|
-
# class Echo < Hanami::CLI::Command
|
|
94
|
-
# desc "Prints given input"
|
|
95
|
-
#
|
|
96
|
-
# def call(*)
|
|
97
|
-
# # ...
|
|
98
|
-
# end
|
|
99
|
-
# end
|
|
100
|
-
def self.desc(description)
|
|
101
|
-
self.description = description
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Describe the usage of the command
|
|
105
|
-
#
|
|
106
|
-
# @param examples [Array<String>] one or more examples
|
|
107
|
-
#
|
|
108
|
-
# @since 0.1.0
|
|
109
|
-
#
|
|
110
|
-
# @example
|
|
111
|
-
# require "hanami/cli"
|
|
112
|
-
#
|
|
113
|
-
# class Server < Hanami::CLI::Command
|
|
114
|
-
# example [
|
|
115
|
-
# " # Basic usage (it uses the bundled server engine)",
|
|
116
|
-
# "--server=webrick # Force `webrick` server engine",
|
|
117
|
-
# "--host=0.0.0.0 # Bind to a host",
|
|
118
|
-
# "--port=2306 # Bind to a port",
|
|
119
|
-
# "--no-code-reloading # Disable code reloading"
|
|
120
|
-
# ]
|
|
121
|
-
#
|
|
122
|
-
# def call(*)
|
|
123
|
-
# # ...
|
|
124
|
-
# end
|
|
125
|
-
# end
|
|
126
|
-
#
|
|
127
|
-
# # $ foo server --help
|
|
128
|
-
# # # ...
|
|
129
|
-
# #
|
|
130
|
-
# # Examples:
|
|
131
|
-
# # foo server # Basic usage (it uses the bundled server engine)
|
|
132
|
-
# # foo server --server=webrick # Force `webrick` server engine
|
|
133
|
-
# # foo server --host=0.0.0.0 # Bind to a host
|
|
134
|
-
# # foo server --port=2306 # Bind to a port
|
|
135
|
-
# # foo server --no-code-reloading # Disable code reloading
|
|
136
|
-
def self.example(*examples)
|
|
137
|
-
self.examples += examples.flatten
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# Specify an argument
|
|
141
|
-
#
|
|
142
|
-
# @param name [Symbol] the argument name
|
|
143
|
-
# @param options [Hash] a set of options
|
|
144
|
-
#
|
|
145
|
-
# @since 0.1.0
|
|
146
|
-
#
|
|
147
|
-
# @example Optional argument
|
|
148
|
-
# require "hanami/cli"
|
|
149
|
-
#
|
|
150
|
-
# class Hello < Hanami::CLI::Command
|
|
151
|
-
# argument :name
|
|
152
|
-
#
|
|
153
|
-
# def call(name: nil, **)
|
|
154
|
-
# if name.nil?
|
|
155
|
-
# puts "Hello, stranger"
|
|
156
|
-
# else
|
|
157
|
-
# puts "Hello, #{name}"
|
|
158
|
-
# end
|
|
159
|
-
# end
|
|
160
|
-
# end
|
|
161
|
-
#
|
|
162
|
-
# # $ foo hello
|
|
163
|
-
# # Hello, stranger
|
|
164
|
-
#
|
|
165
|
-
# # $ foo hello Luca
|
|
166
|
-
# # Hello, Luca
|
|
167
|
-
#
|
|
168
|
-
# @example Required argument
|
|
169
|
-
# require "hanami/cli"
|
|
170
|
-
#
|
|
171
|
-
# class Hello < Hanami::CLI::Command
|
|
172
|
-
# argument :name, required: true
|
|
173
|
-
#
|
|
174
|
-
# def call(name:, **)
|
|
175
|
-
# puts "Hello, #{name}"
|
|
176
|
-
# end
|
|
177
|
-
# end
|
|
178
|
-
#
|
|
179
|
-
# # $ foo hello Luca
|
|
180
|
-
# # Hello, Luca
|
|
181
|
-
#
|
|
182
|
-
# # $ foo hello
|
|
183
|
-
# # ERROR: "foo hello" was called with no arguments
|
|
184
|
-
# # Usage: "foo hello NAME"
|
|
185
|
-
#
|
|
186
|
-
# @example Multiple arguments
|
|
187
|
-
# require "hanami/cli"
|
|
188
|
-
#
|
|
189
|
-
# module Generate
|
|
190
|
-
# class Action < Hanami::CLI::Command
|
|
191
|
-
# argument :app, required: true
|
|
192
|
-
# argument :action, required: true
|
|
193
|
-
#
|
|
194
|
-
# def call(app:, action:, **)
|
|
195
|
-
# puts "Generating action: #{action} for app: #{app}"
|
|
196
|
-
# end
|
|
197
|
-
# end
|
|
198
|
-
# end
|
|
199
|
-
#
|
|
200
|
-
# # $ foo generate action web home
|
|
201
|
-
# # Generating action: home for app: web
|
|
202
|
-
#
|
|
203
|
-
# # $ foo generate action
|
|
204
|
-
# # ERROR: "foo generate action" was called with no arguments
|
|
205
|
-
# # Usage: "foo generate action APP ACTION"
|
|
206
|
-
#
|
|
207
|
-
# @example Description
|
|
208
|
-
# require "hanami/cli"
|
|
209
|
-
#
|
|
210
|
-
# class Hello < Hanami::CLI::Command
|
|
211
|
-
# argument :name, desc: "The name of the person to greet"
|
|
212
|
-
#
|
|
213
|
-
# def call(name: nil, **)
|
|
214
|
-
# # ...
|
|
215
|
-
# end
|
|
216
|
-
# end
|
|
217
|
-
#
|
|
218
|
-
# # $ foo hello --help
|
|
219
|
-
# # Command:
|
|
220
|
-
# # foo hello
|
|
221
|
-
# #
|
|
222
|
-
# # Usage:
|
|
223
|
-
# # foo hello [NAME]
|
|
224
|
-
# #
|
|
225
|
-
# # Arguments:
|
|
226
|
-
# # NAME # The name of the person to greet
|
|
227
|
-
# #
|
|
228
|
-
# # Options:
|
|
229
|
-
# # --help, -h # Print this help
|
|
230
|
-
def self.argument(name, options = {})
|
|
231
|
-
arguments << Argument.new(name, options)
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
# Command line option (aka optional argument)
|
|
235
|
-
#
|
|
236
|
-
# @param name [Symbol] the param name
|
|
237
|
-
# @param options [Hash] a set of options
|
|
238
|
-
#
|
|
239
|
-
# @since 0.1.0
|
|
240
|
-
#
|
|
241
|
-
# @example Basic usage
|
|
242
|
-
# require "hanami/cli"
|
|
243
|
-
#
|
|
244
|
-
# class Console < Hanami::CLI::Command
|
|
245
|
-
# param :engine
|
|
246
|
-
#
|
|
247
|
-
# def call(engine: nil, **)
|
|
248
|
-
# puts "starting console (engine: #{engine || :irb})"
|
|
249
|
-
# end
|
|
250
|
-
# end
|
|
251
|
-
#
|
|
252
|
-
# # $ foo console
|
|
253
|
-
# # starting console (engine: irb)
|
|
254
|
-
#
|
|
255
|
-
# # $ foo console --engine=pry
|
|
256
|
-
# # starting console (engine: pry)
|
|
257
|
-
#
|
|
258
|
-
# @example List values
|
|
259
|
-
# require "hanami/cli"
|
|
260
|
-
#
|
|
261
|
-
# class Console < Hanami::CLI::Command
|
|
262
|
-
# param :engine, values: %w(irb pry ripl)
|
|
263
|
-
#
|
|
264
|
-
# def call(engine: nil, **)
|
|
265
|
-
# puts "starting console (engine: #{engine || :irb})"
|
|
266
|
-
# end
|
|
267
|
-
# end
|
|
268
|
-
#
|
|
269
|
-
# # $ foo console
|
|
270
|
-
# # starting console (engine: irb)
|
|
271
|
-
#
|
|
272
|
-
# # $ foo console --engine=pry
|
|
273
|
-
# # starting console (engine: pry)
|
|
274
|
-
#
|
|
275
|
-
# # $ foo console --engine=foo
|
|
276
|
-
# # Error: Invalid param provided
|
|
277
|
-
#
|
|
278
|
-
# @example Description
|
|
279
|
-
# require "hanami/cli"
|
|
280
|
-
#
|
|
281
|
-
# class Console < Hanami::CLI::Command
|
|
282
|
-
# param :engine, desc: "Force a console engine"
|
|
283
|
-
#
|
|
284
|
-
# def call(engine: nil, **)
|
|
285
|
-
# # ...
|
|
286
|
-
# end
|
|
287
|
-
# end
|
|
288
|
-
#
|
|
289
|
-
# # $ foo console --help
|
|
290
|
-
# # # ...
|
|
291
|
-
# #
|
|
292
|
-
# # Options:
|
|
293
|
-
# # --engine=VALUE # Force a console engine: (irb/pry/ripl)
|
|
294
|
-
# # --help, -h # Print this help
|
|
295
|
-
#
|
|
296
|
-
# @example Boolean
|
|
297
|
-
# require "hanami/cli"
|
|
298
|
-
#
|
|
299
|
-
# class Server < Hanami::CLI::Command
|
|
300
|
-
# param :code_reloading, type: :boolean, default: true
|
|
301
|
-
#
|
|
302
|
-
# def call(code_reloading:, **)
|
|
303
|
-
# puts "staring server (code reloading: #{code_reloading})"
|
|
304
|
-
# end
|
|
305
|
-
# end
|
|
306
|
-
#
|
|
307
|
-
# # $ foo server
|
|
308
|
-
# # starting server (code reloading: true)
|
|
309
|
-
#
|
|
310
|
-
# # $ foo server --no-code-reloading
|
|
311
|
-
# # starting server (code reloading: false)
|
|
312
|
-
#
|
|
313
|
-
# # $ foo server --help
|
|
314
|
-
# # # ...
|
|
315
|
-
# #
|
|
316
|
-
# # Options:
|
|
317
|
-
# # --[no]-code-reloading
|
|
318
|
-
#
|
|
319
|
-
# @example Aliases
|
|
320
|
-
# require "hanami/cli"
|
|
321
|
-
#
|
|
322
|
-
# class Server < Hanami::CLI::Command
|
|
323
|
-
# param :port, aliases: ["-p"]
|
|
324
|
-
#
|
|
325
|
-
# def call(options)
|
|
326
|
-
# puts "staring server (port: #{options.fetch(:port, 2300)})"
|
|
327
|
-
# end
|
|
328
|
-
# end
|
|
329
|
-
#
|
|
330
|
-
# # $ foo server
|
|
331
|
-
# # starting server (port: 2300)
|
|
332
|
-
#
|
|
333
|
-
# # $ foo server --port=2306
|
|
334
|
-
# # starting server (port: 2306)
|
|
335
|
-
#
|
|
336
|
-
# # $ foo server -p 2306
|
|
337
|
-
# # starting server (port: 2306)
|
|
338
|
-
#
|
|
339
|
-
# # $ foo server --help
|
|
340
|
-
# # # ...
|
|
341
|
-
# #
|
|
342
|
-
# # Options:
|
|
343
|
-
# # --port=VALUE, -p VALUE
|
|
344
|
-
def self.option(name, options = {})
|
|
345
|
-
self.options << Option.new(name, options)
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
# @since 0.1.0
|
|
349
|
-
# @api private
|
|
350
|
-
def self.params
|
|
351
|
-
(arguments + options).uniq
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
# @since 0.1.0
|
|
355
|
-
# @api private
|
|
356
|
-
def self.default_params
|
|
357
|
-
params.each_with_object({}) do |param, result|
|
|
358
|
-
result[param.name] = param.default unless param.default.nil?
|
|
359
|
-
end
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
# @since 0.1.0
|
|
363
|
-
# @api private
|
|
364
|
-
def self.required_arguments
|
|
365
|
-
arguments.select(&:required?)
|
|
366
|
-
end
|
|
367
|
-
|
|
368
|
-
# @since 0.1.0
|
|
369
|
-
# @api private
|
|
370
|
-
def self.optional_arguments
|
|
371
|
-
arguments.reject(&:required?)
|
|
372
|
-
end
|
|
373
|
-
|
|
374
|
-
extend Forwardable
|
|
375
|
-
|
|
376
|
-
delegate %i[
|
|
377
|
-
description
|
|
378
|
-
examples
|
|
379
|
-
arguments
|
|
380
|
-
options
|
|
381
|
-
params
|
|
382
|
-
default_params
|
|
383
|
-
required_arguments
|
|
384
|
-
optional_arguments
|
|
385
|
-
] => "self.class"
|
|
386
|
-
|
|
387
|
-
# @since 0.1.0
|
|
388
|
-
# @api private
|
|
389
|
-
attr_reader :command_name
|
|
390
|
-
|
|
391
|
-
# @since 0.1.0
|
|
392
|
-
# @api private
|
|
393
|
-
def initialize(command_name:, **)
|
|
394
|
-
@command_name = command_name
|
|
395
|
-
end
|
|
23
|
+
attr_reader :inflector
|
|
396
24
|
end
|
|
397
25
|
end
|
|
398
26
|
end
|