Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions COMMANDS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# devctl Commands Reference

This document provides a comprehensive list of all commands available in the `devctl` CLI.

## Overview

`devctl` is organized into logical command groups. You can always run `devctl --help` or `devctl [command] --help` to get immediate assistance.

---

## 1. Project Initialization (`devctl init`)

Initialize a new project with a standard boilerplate and optimized configuration.

| Command | Usage | Description |
| :--- | :--- | :--- |
| **Spring Boot** | `devctl init spring [name]` | Downloads a Spring Boot project from start.spring.io. |
| **Angular** | `devctl init angular [name]` | Scaffolds a new Angular project. |
| **Vue.js** | `devctl init vue [name]` | Scaffolds a new Vue 3 project via Vite. |
| **NestJS** | `devctl init nest [name]` | Scaffolds a new NestJS backend. |
| **NodeJS** | `devctl init nodejs [name]` | Scaffolds a clean Express + TypeScript project. |
| **ReactJS** | `devctl init react [name]` | Scaffolds a new React project via Vite. |
| **NextJS** | `devctl init nextjs [name]` | Scaffolds a new NextJS project with App Router. |
| **FastAPI** | `devctl init fastapi [name]` | Scaffolds a new FastAPI (Python) project. |
| **Django** | `devctl init django [name]` | Scaffolds a new Django REST Framework project. |
| **Svelte** | `devctl init svelte [name]` | Scaffolds a new SvelteKit project. |
| **Go** | `devctl init go [name]` | Scaffolds a new Go (Fiber) project. |

### Options
* `--db [postgres|mysql|mongodb]`: Specify the database driver for Spring Boot projects (Default: `postgres`).
* `--port [number]`: Specify a custom local port for the project.

---

## 2. Resource Scaffolding (`devctl add`)

Inject business resources (Entities, Controllers, Services) into your existing project layers.

| Command | Usage | Description |
| :--- | :--- | :--- |
| **Resource** | `devctl add resource [Name]` | Generates a full-stack feature for the given name. |

### Parameters
* `--fields, -f`: Define fields in `name:type` format.
* Example: `devctl add resource Product -f "name:string,price:double"`
* Supported types: `string`, `int`, `double`, `float`, `boolean`, `date`.

---

## 3. Local Orchestration (`devctl run`)

Launch your entire development environment in a single terminal.

| Command | Usage | Description |
| :--- | :--- | :--- |
| **Run** | `devctl run` | Scans for databases, backends, and frontends and runs them. |

### Execution Logic
1. **Databases**: Starts Docker Compose services first and waits for initialization.
2. **Backends**: Launches Spring, Nest, Express, Python, or Go APIs in parallel.
3. **Frontends**: Launches Angular, Vue, React, Svelte, or NextJS dev servers.
4. **Logging**: All output is prefixed by service name and color-coded.

---

## 4. Containerization (`devctl dockerize`)

Generate optimized Dockerfiles for all detected projects.

| Command | Usage | Description |
| :--- | :--- | :--- |
| **Dockerize** | `devctl dockerize [path]` | Scaffolds Multi-stage Dockerfiles for all services. |

### Options
* `--force`: Overwrite existing Dockerfiles.
* `--dry-run`: Preview actions without writing files.

---

## 5. Deployment Preparation (`devctl deploy`)

Prepare for multi-service production or staging deployments.

| Command | Usage | Description |
| :--- | :--- | :--- |
| **Deploy** | `devctl deploy [path]` | Generates a global `docker-compose.yml` for all services. |

### Features
* **Automatic Linking**: Detects database configurations from backends and automatically links them to database services in the global compose file.
* **Context Aware**: Uses relative paths for builds to ensure the compose file is portable.

---

## 6. Utilities

| Command | Usage | Description |
| :--- | :--- | :--- |
| **Ping** | `devctl ping` | Returns "pong" to verify the CLI is operational. |
| **Help** | `devctl --help` | Displays the global or command-specific help menu. |
26 changes: 16 additions & 10 deletions devctl/commands/add.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
"""
CLI command group for adding new resources to existing projects.
Supports Spring Boot, Angular, Vue.js, NestJS, NodeJS, React, NextJS, FastAPI, Django, Svelte, and Go scaffolding.
Supports Spring Boot, Angular, Vue.js, NestJS, NodeJS, React, NextJS, FastAPI,
Django, Svelte, and Go scaffolding.
"""

import os

import typer

from devctl.generators.scaffold_angular import generate_angular_resource
from devctl.generators.scaffold_spring import generate_spring_resource
from devctl.generators.scaffold_vue import generate_vue_resource
from devctl.generators.scaffold_django import generate_django_resource
from devctl.generators.scaffold_fastapi import generate_fastapi_resource
from devctl.generators.scaffold_go import generate_go_resource
from devctl.generators.scaffold_nestjs import generate_nest_resource
from devctl.generators.scaffold_nextjs import generate_nextjs_resource
from devctl.generators.scaffold_nodejs import generate_nodejs_resource
from devctl.generators.scaffold_react import generate_react_resource
from devctl.generators.scaffold_nextjs import generate_nextjs_resource
from devctl.generators.scaffold_fastapi import generate_fastapi_resource
from devctl.generators.scaffold_django import generate_django_resource
from devctl.generators.scaffold_spring import generate_spring_resource
from devctl.generators.scaffold_svelte import generate_svelte_resource
from devctl.generators.scaffold_go import generate_go_resource
from devctl.generators.scaffold_vue import generate_vue_resource
from devctl.orchestrator.scanner import detect_environment
from devctl.utils.dependencies import check_tool

Expand Down Expand Up @@ -98,7 +99,9 @@ def resource(
# Check for NextJS project
if env_state.get("has_nextjs"):
project_detected = True
typer.secho("NextJS project detected. Launching NextJS generator...", fg=typer.colors.YELLOW)
typer.secho(
"NextJS project detected. Launching NextJS generator...", fg=typer.colors.YELLOW
)
try:
generate_nextjs_resource(name, fields, root_path=".")
except Exception as e:
Expand All @@ -107,7 +110,9 @@ def resource(
# Check for FastAPI project
if env_state.get("has_fastapi"):
project_detected = True
typer.secho("FastAPI project detected. Launching FastAPI generator...", fg=typer.colors.CYAN)
typer.secho(
"FastAPI project detected. Launching FastAPI generator...", fg=typer.colors.CYAN
)
try:
generate_fastapi_resource(name, fields, root_path=".")
except Exception as e:
Expand Down Expand Up @@ -154,7 +159,8 @@ def resource(
if not project_detected:
typer.secho(
"Error: Unable to determine project type. "
"Please run from within a supported project directory (Spring, Angular, React, NextJS, FastAPI, Django, Svelte, Go, or Vue.js).",
"Please run from within a supported project directory "
"(Spring, Angular, React, NextJS, FastAPI, Django, Svelte, Go, or Vue.js).",
fg=typer.colors.RED,
)
raise typer.Exit(code=1)
28 changes: 19 additions & 9 deletions devctl/commands/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ def extract_db_info(project_path: Path) -> Optional[Dict[str, Any]]:
# spring.datasource.url=jdbc:postgresql://localhost:5432/sample_api_db
url_match = re.search(r"spring\.datasource\.url=jdbc:([^:]+)://[^:]+:(\d+)/([\w-]+)", content)
# spring.data.mongodb.uri=mongodb://admin:password@localhost:27017/db_name
mongo_match = re.search(r"spring\.data\.mongodb\.uri=mongodb://([^:]+):([^@]+)@[^:]+:(\d+)/([\w-]+)", content)

mongo_match = re.search(
r"spring\.data\.mongodb\.uri=mongodb://([^:]+):([^@]+)@[^:]+:(\d+)/([\w-]+)", content
)

user_match = re.search(r"spring\.datasource\.username=([\w-]+)", content)
pass_match = re.search(r"spring\.datasource\.password=([\w-]+)", content)

Expand All @@ -55,7 +57,7 @@ def extract_db_info(project_path: Path) -> Optional[Dict[str, Any]]:
db_pass = pass_match.group(1) if pass_match else "password"

db_dict = _build_db_dict(db_type, db_port, db_name, db_user, db_pass)
...

# Try to refine service name from existing docker-compose if possible
compose_path = project_path / "docker-compose.yml"
if compose_path.exists():
Expand All @@ -75,7 +77,8 @@ def extract_db_info(project_path: Path) -> Optional[Dict[str, Any]]:
if db_type == "mongodb" and "mongo" in image:
db_dict["service_name"] = s_name
break
except Exception:
except (OSError, yaml.YAMLError):
# Ignore parsing errors; fall back to default service name
pass

return db_dict
Expand Down Expand Up @@ -128,7 +131,9 @@ def extract_db_from_compose(compose_path: Path) -> Optional[Dict[str, Any]]:
db_name = env_dict.get("POSTGRES_DB", "db")
elif db_type == "mysql":
user = env_dict.get("MYSQL_USER", env_dict.get("MYSQL_ROOT_PASSWORD", "admin"))
password = env_dict.get("MYSQL_PASSWORD", env_dict.get("MYSQL_ROOT_PASSWORD", "password"))
password = env_dict.get(
"MYSQL_PASSWORD", env_dict.get("MYSQL_ROOT_PASSWORD", "password")
)
db_name = env_dict.get("MYSQL_DATABASE", "db")
else:
user = env_dict.get("MONGO_INITDB_ROOT_USERNAME", "admin")
Expand All @@ -145,7 +150,12 @@ def extract_db_from_compose(compose_path: Path) -> Optional[Dict[str, Any]]:

db_dict = _build_db_dict(
db_type,
host_port or ("5432" if db_type == "postgresql" else ("3306" if db_type == "mysql" else "27017")),
host_port
or (
"5432"
if db_type == "postgresql"
else ("3306" if db_type == "mysql" else "27017")
),
db_name,
user,
password,
Expand All @@ -159,7 +169,6 @@ def extract_db_from_compose(compose_path: Path) -> Optional[Dict[str, Any]]:
def _build_db_dict(db_type: str, port: str, name: str, user: str, password: str) -> Dict[str, Any]:
is_postgres = db_type == "postgresql"
is_mysql = db_type == "mysql"
is_mongo = db_type == "mongodb"

if is_postgres:
internal_port = "5432"
Expand Down Expand Up @@ -210,7 +219,6 @@ def _build_db_dict(db_type: str, port: str, name: str, user: str, password: str)
}



@app.command()
def deploy(path: Path = PATH_ARGUMENT):
"""
Expand All @@ -225,7 +233,9 @@ def deploy(path: Path = PATH_ARGUMENT):
raise typer.Exit(1) from e

if not projects:
typer.secho("Error: No supported projects (Spring, Angular, Vue) found.", fg=typer.colors.RED)
typer.secho(
"Error: No supported projects (Spring, Angular, Vue) found.", fg=typer.colors.RED
)
raise typer.Exit(1)

services_data = []
Expand Down
19 changes: 10 additions & 9 deletions devctl/commands/init.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
"""
CLI command group for initializing new projects.
Supports Spring Boot, Angular, Vue.js, NestJS, NodeJS, React, NextJS, FastAPI, Django, Svelte, and Go.
Supports Spring Boot, Angular, Vue.js, NestJS, NodeJS, React, NextJS, FastAPI,
Django, Svelte, and Go.
"""

import typer

# Angular generator
from devctl.generators.angular import generate_angular_boilerplate

# Spring generator
from devctl.generators.spring import download_spring_boilerplate
from devctl.generators.vue import generate_vue_boilerplate
from devctl.generators.django import generate_django_boilerplate
from devctl.generators.fastapi import generate_fastapi_boilerplate
from devctl.generators.go_fiber import generate_go_boilerplate
from devctl.generators.nestjs import generate_nest_boilerplate
from devctl.generators.nextjs import generate_nextjs_boilerplate
from devctl.generators.nodejs import generate_nodejs_boilerplate
from devctl.generators.react import generate_react_boilerplate
from devctl.generators.nextjs import generate_nextjs_boilerplate
from devctl.generators.fastapi import generate_fastapi_boilerplate
from devctl.generators.django import generate_django_boilerplate

# Spring generator
from devctl.generators.spring import download_spring_boilerplate
from devctl.generators.svelte import generate_svelte_boilerplate
from devctl.generators.go_fiber import generate_go_boilerplate
from devctl.generators.vue import generate_vue_boilerplate
from devctl.orchestrator.config_builder import generate_config
from devctl.utils.dependencies import check_tool

Expand Down
23 changes: 14 additions & 9 deletions devctl/commands/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
Automatically detects and launches backend, frontend, and database services.
"""

import typer
from pathlib import Path

from devctl.orchestrator.runner import launch_dev_environment
import typer

from devctl.generators.docker_scaffold import discover_docker_projects
from devctl.orchestrator.runner import launch_dev_environment
from devctl.utils.dependencies import check_tool

app = typer.Typer(help="Local execution and development commands.")
Expand All @@ -22,18 +23,18 @@ def run_env(ctx: typer.Context):
return

typer.secho("Analyzing the current directory tree...", fg=typer.colors.CYAN)

projects = discover_docker_projects(".")

# Check for docker-compose.yml files
docker_composes = []
for p in Path(".").rglob("docker-compose.yml"):
if "node_modules" not in str(p) and "target" not in str(p) and ".git" not in str(p):
docker_composes.append(p.parent)

has_spring = any(p.kind == "spring" for p in projects)
has_angular = any(p.kind == "angular" for p in projects)
has_vue = any(p.kind == "vue" for p in projects)
any(p.kind == "spring" for p in projects)
any(p.kind == "angular" for p in projects)
any(p.kind == "vue" for p in projects)
has_docker = len(docker_composes) > 0

# Check dependencies based on detection
Expand All @@ -47,10 +48,14 @@ def run_env(ctx: typer.Context):

# Visual summary of detection for the user
def get_status(condition: bool):
return typer.style("FOUND", fg=typer.colors.GREEN) if condition else typer.style("MISSING", fg=typer.colors.RED)
return (
typer.style("FOUND", fg=typer.colors.GREEN)
if condition
else typer.style("MISSING", fg=typer.colors.RED)
)

typer.echo(f" - Docker Compose ({len(docker_composes)}) : {get_status(has_docker)}")

for kind in sorted(counts.keys()):
typer.echo(f" - {kind.capitalize()} ({counts[kind]}) : {get_status(True)}")

Expand Down
4 changes: 1 addition & 3 deletions devctl/generators/angular.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ def generate_angular_boilerplate(project_name: str) -> bool:
try:
command = ["ng", "new", safe_name, "--routing=true", "--style=scss", "--skip-git=true"]

typer.secho(
"Downloading npm packages... (This may take 1-2 minutes)", fg=typer.colors.CYAN
)
typer.secho("Downloading npm packages... (This may take 1-2 minutes)", fg=typer.colors.CYAN)
subprocess.run(command, check=True)

# Post-installation configuration
Expand Down
Loading
Loading