Class: Tina4::CLI

Inherits:
Object
  • Object
show all
Defined in:
lib/tina4/cli.rb

Constant Summary collapse

GENERATORS =

── Command registries — the single source of truth ─────────────────

ONE entry per command/generator drives dispatch (#run / #cmd_generate), the human help (#cmd_help), AND the machine-readable manifest (commands --json). Add a command in ONE place and it appears in dispatch, help, and discovery — there is no second list to sync. Ruby mirror of the Python master's COMMANDS / GENERATORS registries (tina4_python/cli/init.py).

GENERATORS[name] = { handler: :method_symbol, usage: str, summary: str }
COMMANDS[name]   = { handler: :method_symbol, summary: str,
                   usage?: str,          # arg/flag hint for #cmd_help (human only)
                   args?: [str],         # positional args for the manifest ("x?" = optional)
                   subcommands?: [str] } # sub-names for the manifest (generate)

Handlers are instance-method symbols dispatched via #send: GENERATORS handlers take (name, flags); COMMANDS handlers take (argv).

{
  "model"      => { handler: :generate_model,      usage: '<Name> [--fields "name:string,price:float"]', summary: "ORM model + matching migration" },
  "route"      => { handler: :generate_route,      usage: "<name> [--model Name] [--public]",             summary: "CRUD route file, secure by default (--public opens writes)" },
  "crud"       => { handler: :generate_crud,       usage: '<Name> [--fields "..."] [--public]',           summary: "Model + migration + routes + form + view + test" },
  "migration"  => { handler: :generate_migration,  usage: "<description>",                                 summary: "Timestamped migration file (UP/DOWN)" },
  "middleware" => { handler: :generate_middleware, usage: "<Name>",                                        summary: "Middleware with before/after hooks" },
  "test"       => { handler: :generate_test,       usage: "<name> [--model Name]",                         summary: "RSpec test file" },
  "form"       => { handler: :generate_form,       usage: '<Name> [--fields "..."]',                       summary: "Form template with inputs matching model fields" },
  "view"       => { handler: :generate_view,       usage: '<Name> [--fields "..."]',                       summary: "List + detail view templates" },
  "auth"       => { handler: :generate_auth,       usage: "",                                              summary: "Login/register routes + User model + templates" },
  "service"    => { handler: :generate_service,    usage: '<Name> [--every 5m | --cron "..."]',            summary: "Scheduled ServiceRunner task (src/services/)" },
  "queue"      => { handler: :generate_queue,      usage: "<topic>",                                       summary: "Producer + consumer worker (src/services/)" },
  "validator"  => { handler: :generate_validator,  usage: "<Name>",                                        summary: "Request-body Validator (src/validators/)" },
  "seeder"     => { handler: :generate_seeder,     usage: "<Model>",                                       summary: "FakeData + seed_orm seeder (seeds/)" },
  "websocket"  => { handler: :generate_websocket,  usage: "<path>",                                        summary: "Tina4.websocket handler (src/routes/)" },
  "listener"   => { handler: :generate_listener,   usage: "<event>",                                       summary: "Tina4::Events.on listener (src/listeners/)" },
}.freeze
QUEUE_SUBCOMMANDS =

Sub-dispatch table for the top-level queue command — the SINGLE source for its subcommands (drives #cmd_queue dispatch AND the manifest's queue.subcommands). Ruby mirror of the Python master's _QUEUE_SUBCOMMANDS. Distinct from the queue GENERATOR, which SCAFFOLDS a consumer file.

{
  "work"  => :queue_work,
  "stats" => :queue_stats,
  "retry" => :queue_retry,
  "clear" => :queue_clear,
}.freeze
COMMANDS =
{
  "init"             => { handler: :cmd_init,             usage: "[NAME]", args: ["name?"],           summary: "Initialize a new Tina4 project" },
  "start"            => { handler: :cmd_start,            usage: "[options]",                          summary: "Start the Tina4 web server" },
  "serve"            => { handler: :cmd_start,                                                         summary: "Alias for start" },
  "migrate"          => { handler: :cmd_migrate,          usage: "[--create NAME] [--rollback N]",     summary: "Run database migrations" },
  "migrate:create"   => { handler: :cmd_migrate_create,   usage: "<desc>", args: ["description"],      summary: "Create a new migration file" },
  "migrate:status"   => { handler: :cmd_migrate_status,                                                summary: "Show migration status (completed and pending)" },
  "migrate:rollback" => { handler: :cmd_migrate_rollback, usage: "[-n N]",                             summary: "Rollback the last batch of migrations" },
  "seed"             => { handler: :cmd_seed,             usage: "[--clear]",                          summary: "Run all seed files in seeds/" },
  "seed:create"      => { handler: :cmd_seed_create,      usage: "NAME", args: ["name"],               summary: "Create a new seed file" },
  "test"             => { handler: :cmd_test,                                                          summary: "Run inline tests" },
  "queue"            => { handler: :cmd_queue,            usage: "<work|stats|retry|clear> [topic]", subcommands: QUEUE_SUBCOMMANDS.keys, summary: "Run queue workers and manage jobs" },
  "build"            => { handler: :cmd_build,            usage: "[--tag NAME] [--file PATH]",         summary: "Build the deployable Docker image" },
  "version"          => { handler: :cmd_version,                                                       summary: "Show Tina4 version" },
  "routes"           => { handler: :cmd_routes,                                                        summary: "List all registered routes" },
  "console"          => { handler: :cmd_console,                                                       summary: "Start an interactive console" },
  "generate"         => { handler: :cmd_generate,         usage: "<what> <name> [options]", subcommands: GENERATORS.keys, summary: "Generate scaffolding (see Generators below)" },
  "ai"               => { handler: :cmd_ai,               usage: "[--all]",                            summary: "Detect AI tools and install context files" },
  "metrics"          => { handler: :cmd_metrics,          usage: "[--top N] [--json] [--fail-on warn|error] [--path DIR]", summary: "Rank top code-quality offenders" },
  "commands"         => { handler: :cmd_commands,         usage: "[--json]",                           summary: "List available commands (add --json for machine form)" },
  "help"             => { handler: :cmd_help,                                                          summary: "Show this help message" },
}.freeze
FIELD_TYPE_MAP =

── Field type mapping ──────────────────────────────────────────────

{
  "string"   => { orm: "string_field",  sql: "VARCHAR(255)", default: "''" },
  "str"      => { orm: "string_field",  sql: "VARCHAR(255)", default: "''" },
  "int"      => { orm: "integer_field", sql: "INTEGER",      default: "0" },
  "integer"  => { orm: "integer_field", sql: "INTEGER",      default: "0" },
  "float"    => { orm: "float_field",   sql: "REAL",         default: "0" },
  "numeric"  => { orm: "float_field",   sql: "REAL",         default: "0" },
  "decimal"  => { orm: "float_field",   sql: "REAL",         default: "0" },
  "bool"     => { orm: "boolean_field", sql: "INTEGER",      default: "0" },
  "boolean"  => { orm: "boolean_field", sql: "INTEGER",      default: "0" },
  "text"     => { orm: "string_field",  sql: "TEXT",         default: "''" },
  "datetime" => { orm: "string_field",  sql: "TEXT",         default: "NULL" },
  "blob"     => { orm: "string_field",  sql: "BLOB",         default: "NULL" },
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.start(argv) ⇒ Object



94
95
96
# File 'lib/tina4/cli.rb', line 94

def self.start(argv)
  new.run(argv)
end

Instance Method Details

#run(argv) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/tina4/cli.rb', line 98

def run(argv)
  command = argv.shift || "help"
  command = "help" if %w[-h --help].include?(command)

  # Dispatch from the single-source-of-truth COMMANDS registry. The same
  # registry drives #cmd_help and the `commands --json` manifest, so
  # dispatch, help, and discovery never drift.
  spec = COMMANDS[command]
  if spec
    send(spec[:handler], argv)
  else
    puts "Unknown command: #{command}"
    cmd_help
    exit 1
  end
end