587 lines
18 KiB
Ruby
Executable File
587 lines
18 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
# frozen_string_literal: true
|
|
|
|
# rubocop:disable Metrics/LineLength
|
|
$LOAD_PATH.unshift __dir__ + "/../../lib"
|
|
require "dry/cli"
|
|
|
|
module Foo
|
|
module CLI
|
|
module Commands
|
|
extend Dry::CLI::Registry
|
|
|
|
class Command < Dry::CLI::Command
|
|
end
|
|
|
|
module Assets
|
|
class Precompile < Dry::CLI::Command
|
|
desc "Precompile assets for deployment"
|
|
|
|
example [
|
|
"FOO_ENV=production # Precompile assets for production environment"
|
|
]
|
|
|
|
def call(*); end
|
|
end
|
|
end
|
|
|
|
class Console < Dry::CLI::Command
|
|
desc "Starts Foo console"
|
|
option :engine, desc: "Force a console engine", values: %w[irb pry ripl]
|
|
|
|
example [
|
|
" # Uses the bundled engine",
|
|
"--engine=pry # Force to use Pry"
|
|
]
|
|
|
|
def call(engine: nil, **)
|
|
puts "console - engine: #{engine}"
|
|
end
|
|
end
|
|
|
|
module DB
|
|
class Apply < Dry::CLI::Command
|
|
desc "Migrate, dump the SQL schema, and delete the migrations (experimental)"
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Console < Dry::CLI::Command
|
|
desc "Starts a database console"
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Create < Dry::CLI::Command
|
|
desc "Create the database (only for development/test)"
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Drop < Dry::CLI::Command
|
|
desc "Drop the database (only for development/test)"
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Migrate < Dry::CLI::Command
|
|
desc "Migrate the database"
|
|
argument :version, desc: "The target version of the migration (see `foo db version`)"
|
|
|
|
example [
|
|
" # Migrate to the last version",
|
|
"20170721120747 # Migrate to a specific version"
|
|
]
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Prepare < Dry::CLI::Command
|
|
desc "Drop, create, and migrate the database (only for development/test)"
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Version < Dry::CLI::Command
|
|
desc "Print the current migrated version"
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Rollback < Dry::CLI::Command
|
|
desc "Rollback the database"
|
|
|
|
argument :steps, desc: "Number of versions to rollback", default: 1
|
|
|
|
def call(steps:, **)
|
|
puts steps
|
|
end
|
|
end
|
|
end
|
|
|
|
module Destroy
|
|
class Action < Dry::CLI::Command
|
|
desc "Destroy an action from app"
|
|
|
|
example [
|
|
"web home#index # Basic usage",
|
|
"admin users#index # Destroy from `admin` app"
|
|
]
|
|
|
|
argument :app, required: true, desc: "The application name (eg. `web`)"
|
|
argument :action, required: true, desc: "The action name (eg. `home#index`)"
|
|
|
|
def call(app:, action:, **)
|
|
puts "destroy action - app: #{app}, action: #{action}"
|
|
end
|
|
end
|
|
|
|
class App < Dry::CLI::Command
|
|
desc "Destroy an app"
|
|
|
|
argument :app, required: true, desc: "The application name (eg. `web`)"
|
|
|
|
example [
|
|
"admin # Destroy `admin` app"
|
|
]
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Mailer < Dry::CLI::Command
|
|
desc "Destroy a mailer"
|
|
|
|
argument :mailer, required: true, desc: "The mailer name (eg. `welcome`)"
|
|
|
|
example [
|
|
"welcome # Destroy `WelcomeMailer` mailer"
|
|
]
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Migration < Dry::CLI::Command
|
|
desc "Destroy a migration"
|
|
|
|
argument :migration, required: true, desc: "The migration name (eg. `create_users`)"
|
|
|
|
example [
|
|
"create_users # Destroy `db/migrations/20170721120747_create_users.rb`"
|
|
]
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Model < Dry::CLI::Command
|
|
desc "Destroy a model"
|
|
|
|
argument :model, required: true, desc: "The model name (eg. `user`)"
|
|
|
|
example [
|
|
"user # Destroy `User` entity and `UserRepository` repository"
|
|
]
|
|
|
|
def call(*); end
|
|
end
|
|
end
|
|
|
|
module Generate
|
|
class Action < Dry::CLI::Command
|
|
desc "Generate an action for app"
|
|
|
|
example [
|
|
"web home#index # Basic usage",
|
|
"admin home#index # Generate for `admin` app",
|
|
"web home#index --url=/ # Specify URL",
|
|
"web sessions#destroy --method=GET # Specify HTTP method",
|
|
"web books#create --skip-view # Skip view and template"
|
|
]
|
|
|
|
argument :app, required: true, desc: "The application name (eg. `web`)"
|
|
argument :action, required: true, desc: "The action name (eg. `home#index`)"
|
|
|
|
option :url, desc: "The action URL"
|
|
option :method, desc: "The action HTTP method"
|
|
option :skip_view, type: :boolean, default: false, desc: "Skip view and template"
|
|
|
|
def call(app:, action:, **options)
|
|
puts "generate action - app: #{app}, action: #{action}, options: #{options.inspect}"
|
|
end
|
|
end
|
|
|
|
class App < Dry::CLI::Command
|
|
desc "Generate an app"
|
|
|
|
argument :app, required: true, desc: "The application name (eg. `web`)"
|
|
option :application_base_url, desc: "The app base URL (eg. `/api/v1`)"
|
|
|
|
example [
|
|
"admin # Generate `admin` app",
|
|
"api --application-base-url=/api/v1 # Generate `api` app and mount at `/api/v1`"
|
|
]
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Mailer < Dry::CLI::Command
|
|
desc "Generate a mailer"
|
|
|
|
argument :mailer, required: true, desc: "The mailer name (eg. `welcome`)"
|
|
|
|
option :from, desc: "The default `from` field of the mail"
|
|
option :to, desc: "The default `to` field of the mail"
|
|
option :subject, desc: "The mail subject"
|
|
|
|
example [
|
|
"welcome # Basic usage",
|
|
'welcome --from="noreply@example.com" # Generate with default `from` value',
|
|
'announcement --to="users@example.com" # Generate with default `to` value',
|
|
'forgot_password --subject="Your password reset" # Generate with default `subject`'
|
|
]
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Migration < Dry::CLI::Command
|
|
desc "Generate a migration"
|
|
|
|
argument :migration, required: true, desc: "The migration name (eg. `create_users`)"
|
|
|
|
example [
|
|
"create_users # Generate `db/migrations/20170721120747_create_users.rb`"
|
|
]
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Model < Dry::CLI::Command
|
|
desc "Generate a model"
|
|
|
|
argument :model, required: true, desc: "Model name (eg. `user`)"
|
|
option :skip_migration, type: :boolean, default: false, desc: "Skip migration"
|
|
|
|
example [
|
|
"user # Generate `User` entity, `UserRepository` repository, and the migration",
|
|
"user --skip-migration # Generate `User` entity and `UserRepository` repository"
|
|
]
|
|
|
|
def call(model:, **)
|
|
puts "generate model - model: #{model}"
|
|
end
|
|
end
|
|
|
|
class Secret < Dry::CLI::Command
|
|
desc "Generate session secret"
|
|
|
|
argument :app, desc: "The application name (eg. `web`)"
|
|
|
|
example [
|
|
" # Prints secret (eg. `6fad60e21f3f6bfcaf8e56cdb0f835d644b4892c3badc58328126812429bf073`)",
|
|
"web # Prints session secret (eg. `WEB_SESSIONS_SECRET=6fad60e21f3f6bfcaf8e56cdb0f835d644b4892c3badc58328126812429bf073`)"
|
|
]
|
|
|
|
def call(app: nil, **)
|
|
puts "generate secret - app: #{app}"
|
|
end
|
|
end
|
|
end
|
|
|
|
class New < Dry::CLI::Command
|
|
desc "Generate a new Foo project"
|
|
argument :project, required: true
|
|
|
|
option :database, desc: "Database (sqlite/postgres/mysql)", default: "sqlite", aliases: ["-d", "--db"]
|
|
option :application_name, desc: "App name", default: "web"
|
|
option :application_base_url, desc: "App base URL", default: "/"
|
|
option :template, desc: "Template engine (erb/haml/slim)", default: "erb"
|
|
option :test, desc: "Project testing framework (minitest/rspec)", default: "minitest"
|
|
option :foo_head, desc: "Use Foo HEAD (true/false)", type: :boolean, default: false
|
|
|
|
example [
|
|
"bookshelf # Basic usage",
|
|
"bookshelf --test=rspec # Setup RSpec testing framework",
|
|
"bookshelf --database=postgres # Setup Postgres database",
|
|
"bookshelf --template=slim # Setup Slim template engine",
|
|
"bookshelf --foo-head # Use Foo HEAD"
|
|
]
|
|
|
|
def call(project:, **)
|
|
puts "new - project: #{project}"
|
|
end
|
|
end
|
|
|
|
class Routes < Dry::CLI::Command
|
|
desc "Print routes"
|
|
|
|
def call(*); end
|
|
end
|
|
|
|
class Server < Dry::CLI::Command
|
|
desc "Start Foo server (only for development)"
|
|
|
|
option :server, desc: "Force a server engine (eg, webrick, puma, thin, etc..)"
|
|
option :host, desc: "The host address to bind to"
|
|
option :port, desc: "The port to run the server on", aliases: ["-p"]
|
|
option :debug, desc: "Turn on debug output"
|
|
option :warn, desc: "Turn on warnings"
|
|
option :daemonize, desc: "Daemonize the server"
|
|
option :pid, desc: "Path to write a pid file after daemonize"
|
|
option :code_reloading, desc: "Code reloading", type: :boolean, default: true
|
|
|
|
example [
|
|
" # Basic usage (it uses the bundled server engine)",
|
|
"--server=webrick # Force `webrick` server engine",
|
|
"--host=0.0.0.0 # Bind to a host",
|
|
"--port=2306 # Bind to a port",
|
|
"--no-code-reloading # Disable code reloading"
|
|
]
|
|
|
|
def call(options)
|
|
puts "server - #{options.inspect}"
|
|
end
|
|
end
|
|
|
|
class Version < Dry::CLI::Command
|
|
desc "Print Foo version"
|
|
|
|
def call(*)
|
|
puts "v1.0.0"
|
|
end
|
|
end
|
|
|
|
class Exec < Dry::CLI::Command
|
|
desc "Execute a task"
|
|
|
|
argument :task, desc: "Task to execute", type: :string, required: true
|
|
argument :dirs, desc: "Directories", type: :array, required: false
|
|
|
|
def call(task:, dirs: [], **)
|
|
puts "exec - Task: #{task} - Directories: #{dirs.inspect}"
|
|
end
|
|
end
|
|
|
|
class Hello < Dry::CLI::Command
|
|
def call(*)
|
|
raise NotImplementedError
|
|
end
|
|
end
|
|
|
|
class Greeting < Dry::CLI::Command
|
|
argument :response, default: "Hello World"
|
|
|
|
option :person
|
|
|
|
def call(response:, **options)
|
|
puts "response: #{response}, person: #{options[:person]}"
|
|
end
|
|
end
|
|
|
|
class VariadicArguments < Dry::CLI::Command
|
|
desc "accept multiple arguments at the end of the command"
|
|
|
|
def call(**options)
|
|
puts "Unused Arguments: #{options[:args].join(", ")}"
|
|
end
|
|
end
|
|
|
|
class MandatoryAndVariadicArguments < Dry::CLI::Command
|
|
desc "require one command and accept multiple unused arguments"
|
|
|
|
argument :first, desc: "mandatory first argument", required: true
|
|
|
|
def call(first:, **options)
|
|
puts "first: #{first}"
|
|
puts "Unused Arguments: #{options[:args].join(", ")}"
|
|
end
|
|
end
|
|
|
|
class MandatoryOptionsAndVariadicArguments < Dry::CLI::Command
|
|
desc "require one command, accept options and multiple unused arguments"
|
|
|
|
argument :first, desc: "mandatory first argument", required: true
|
|
option :url, desc: "The action URL"
|
|
option :method, desc: "The action HTTP method"
|
|
|
|
def call(first:, **options)
|
|
puts "first: #{first}"
|
|
puts "url: #{options[:url]}"
|
|
puts "method: #{options[:method]}"
|
|
puts "Unused Arguments: #{options[:args].join(", ")}"
|
|
end
|
|
end
|
|
|
|
module Sub
|
|
class Command < Dry::CLI::Command
|
|
def call(*)
|
|
raise NotImplementedError
|
|
end
|
|
end
|
|
end
|
|
|
|
class RootCommand < Dry::CLI::Command
|
|
desc "Root command with arguments and subcommands"
|
|
argument :root_command_argument, desc: "Root command argument", required: true
|
|
option :root_command_option, desc: "Root command option"
|
|
|
|
def call(**params)
|
|
puts "I'm a root-command argument:#{params[:root_command_argument]}"
|
|
puts "I'm a root-command option:#{params[:root_command_option]}"
|
|
end
|
|
end
|
|
|
|
module RootCommands
|
|
class SubCommand < Dry::CLI::Command
|
|
desc "Root command sub command"
|
|
argument :root_command_sub_command_argument, desc: "Root command sub command argument", required: true
|
|
option :root_command_sub_command_option, desc: "Root command sub command option"
|
|
|
|
def call(**params)
|
|
puts "I'm a root-command sub-command argument:#{params[:root_command_sub_command_argument]}"
|
|
puts "I'm a root-command sub-command option:#{params[:root_command_sub_command_option]}"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
Foo::CLI::Commands.register "assets precompile", Foo::CLI::Commands::Assets::Precompile
|
|
Foo::CLI::Commands.register "console", Foo::CLI::Commands::Console
|
|
Foo::CLI::Commands.register "db" do |prefix|
|
|
prefix.register "apply", Foo::CLI::Commands::DB::Apply
|
|
prefix.register "console", Foo::CLI::Commands::DB::Console
|
|
prefix.register "create", Foo::CLI::Commands::DB::Create
|
|
prefix.register "drop", Foo::CLI::Commands::DB::Drop
|
|
prefix.register "migrate", Foo::CLI::Commands::DB::Migrate
|
|
prefix.register "prepare", Foo::CLI::Commands::DB::Prepare
|
|
prefix.register "version", Foo::CLI::Commands::DB::Version
|
|
prefix.register "rollback", Foo::CLI::Commands::DB::Rollback
|
|
end
|
|
Foo::CLI::Commands.register "destroy", aliases: ["d"] do |prefix|
|
|
prefix.register "action", Foo::CLI::Commands::Destroy::Action
|
|
prefix.register "app", Foo::CLI::Commands::Destroy::App
|
|
prefix.register "mailer", Foo::CLI::Commands::Destroy::Mailer
|
|
prefix.register "migration", Foo::CLI::Commands::Destroy::Migration
|
|
prefix.register "model", Foo::CLI::Commands::Destroy::Model
|
|
end
|
|
Foo::CLI::Commands.register "generate", aliases: ["g"] do |prefix|
|
|
prefix.register "action", Foo::CLI::Commands::Generate::Action
|
|
prefix.register "app", Foo::CLI::Commands::Generate::App
|
|
prefix.register "mailer", Foo::CLI::Commands::Generate::Mailer
|
|
prefix.register "migration", Foo::CLI::Commands::Generate::Migration
|
|
prefix.register "model", Foo::CLI::Commands::Generate::Model
|
|
prefix.register "secret", Foo::CLI::Commands::Generate::Secret
|
|
end
|
|
Foo::CLI::Commands.register "new", Foo::CLI::Commands::New
|
|
Foo::CLI::Commands.register "routes", Foo::CLI::Commands::Routes
|
|
Foo::CLI::Commands.register "server", Foo::CLI::Commands::Server, aliases: ["s"]
|
|
Foo::CLI::Commands.register "version", Foo::CLI::Commands::Version, aliases: ["v", "-v", "--version"]
|
|
Foo::CLI::Commands.register "exec", Foo::CLI::Commands::Exec
|
|
|
|
Foo::CLI::Commands.register "hello", Foo::CLI::Commands::Hello
|
|
Foo::CLI::Commands.register "greeting", Foo::CLI::Commands::Greeting
|
|
Foo::CLI::Commands.register "sub command", Foo::CLI::Commands::Sub::Command
|
|
Foo::CLI::Commands.register "root-command", Foo::CLI::Commands::RootCommand
|
|
Foo::CLI::Commands.register "root-command sub-command", Foo::CLI::Commands::RootCommands::SubCommand
|
|
|
|
Foo::CLI::Commands.register "variadic default", Foo::CLI::Commands::VariadicArguments
|
|
Foo::CLI::Commands.register "variadic with-mandatory", Foo::CLI::Commands::MandatoryAndVariadicArguments
|
|
Foo::CLI::Commands.register "variadic with-mandatory-and-options", Foo::CLI::Commands::MandatoryOptionsAndVariadicArguments
|
|
|
|
module Foo
|
|
module Webpack
|
|
module CLI
|
|
class Generate < Dry::CLI::Command
|
|
desc "Generate webpack configuration"
|
|
|
|
option :apps, desc: "Generate webpack apps", type: :array
|
|
|
|
def call(apps: [], **)
|
|
puts "generate webpack. Apps: #{apps}"
|
|
end
|
|
end
|
|
|
|
class Hello < Dry::CLI::Command
|
|
desc "Print a greeting"
|
|
|
|
def call(*)
|
|
puts "hello from webpack"
|
|
end
|
|
end
|
|
|
|
class SubCommand < Dry::CLI::Command
|
|
desc "Override a subcommand"
|
|
|
|
def call(**)
|
|
puts "override from webpack"
|
|
end
|
|
end
|
|
|
|
class CallbacksCommand < Dry::CLI::Command
|
|
desc "Command with callbacks"
|
|
argument :dir, required: true
|
|
option :url
|
|
|
|
def call(dir:, url: nil, **)
|
|
puts "dir: #{dir}, url: #{url.inspect}"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
Foo::CLI::Commands.register "generate webpack", Foo::Webpack::CLI::Generate
|
|
Foo::CLI::Commands.register "hello", Foo::Webpack::CLI::Hello
|
|
Foo::CLI::Commands.register "sub command", Foo::Webpack::CLI::SubCommand
|
|
Foo::CLI::Commands.register "callbacks", Foo::Webpack::CLI::CallbacksCommand
|
|
|
|
# we need to be sure that command will not override with nil command
|
|
Foo::CLI::Commands.register "generate webpack", nil
|
|
|
|
Foo::CLI::Commands.before("callbacks") do |args|
|
|
puts "before command callback #{self.class.name} #{args.inspect}"
|
|
end
|
|
|
|
Foo::CLI::Commands.after("callbacks") do |args|
|
|
puts "after command callback #{self.class.name} #{args.inspect}"
|
|
end
|
|
|
|
module Callbacks
|
|
class BeforeClass
|
|
def call(args)
|
|
puts "before callback (class), #{count(args)} arg(s): #{args.inspect}"
|
|
end
|
|
|
|
private
|
|
|
|
def count(args)
|
|
args.count
|
|
end
|
|
end
|
|
|
|
class AfterClass
|
|
def call(args)
|
|
puts "after callback (class), #{count(args)} arg(s): #{args.inspect}"
|
|
end
|
|
|
|
private
|
|
|
|
def count(args)
|
|
args.count
|
|
end
|
|
end
|
|
|
|
class Before
|
|
def call(args)
|
|
puts "before callback (object), #{count(args)} arg(s): #{args.inspect}"
|
|
end
|
|
|
|
private
|
|
|
|
def count(args)
|
|
args.count
|
|
end
|
|
end
|
|
|
|
class After
|
|
def call(args)
|
|
puts "after callback (object), #{count(args)} arg(s): #{args.inspect}"
|
|
end
|
|
|
|
private
|
|
|
|
def count(args)
|
|
args.count
|
|
end
|
|
end
|
|
end
|
|
# rubocop:enable Metrics/LineLength
|
|
|
|
Foo::CLI::Commands.before("callbacks", Callbacks::BeforeClass)
|
|
Foo::CLI::Commands.after("callbacks", Callbacks::AfterClass)
|
|
Foo::CLI::Commands.before("callbacks", Callbacks::Before.new)
|
|
Foo::CLI::Commands.after("callbacks", Callbacks::After.new)
|
|
|
|
cli = Dry::CLI.new(Foo::CLI::Commands)
|
|
cli.call
|