nest-rs-cli 0.1.0

Scaffolding CLI for nestrs — new projects, feature generators, and project health checks.
//! **Workspace mode** — monorepo: `crates/features/` + thin `apps/*` binaries.
//!
//! Generated by `nestrs new <name>`. Product logic lives in
//! features; each app root `module.rs` composes edge modules only.
//! Contrasts with [`super::standalone`] (single crate, logic in `src/`).

/// Root `Cargo.toml` for a greenfield NestRS monorepo (crates.io deps).
pub const ROOT_CARGO: &str = r#"[workspace]
resolver = "2"
members = ["crates/*", "apps/*"]

[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.95"

[workspace.dependencies]
anyhow = "1"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
features = { path = "crates/features" }
nest-rs-core = "0.1"
nest-rs-config = "0.1"
nest-rs-guards = "0.1"
nest-rs-http = "0.1"
nest-rs-interceptors = "0.1"
nest-rs-opentelemetry = { version = "0.1", features = ["http"] }
nest-rs-testing = "0.1"
poem = { version = "3", features = ["tower-compat", "anyhow", "rustls"] }
"#;

pub const FEATURES_CARGO: &str = r#"[package]
name = "features"
version.workspace = true
edition.workspace = true
publish = false

[dependencies]
nest-rs-core.workspace = true
nest-rs-guards.workspace = true
nest-rs-http.workspace = true
nest-rs-interceptors.workspace = true
poem.workspace = true
"#;

pub const FEATURES_LIB: &str = r#"//! Product features — vertical slices shared across apps.
//!
//! Add one with: `nestrs g feature <name>` (port) or `nestrs g feature <name> --http`.
"#;

pub const FEATURES_LIB_WITH_HELLO: &str = r#"//! Product features — vertical slices shared across apps.

pub mod hello;

pub use hello::HelloHttpModule;
"#;

pub const HELLO_MOD: &str = r#"mod module;
mod service;

pub mod http;

pub use http::HelloHttpModule;
pub use module::HelloModule;
pub use service::HelloService;
"#;

pub const HELLO_MODULE: &str = r#"use nest_rs_core::module;

use super::service::HelloService;

#[module(providers = [HelloService])]
pub struct HelloModule;
"#;

pub const HELLO_SERVICE: &str = r#"use nest_rs_core::injectable;

#[injectable]
#[derive(Default)]
pub struct HelloService;

impl HelloService {
    pub fn greeting(&self) -> String {
        "Hello World".to_string()
    }
}
"#;

pub const HELLO_HTTP_MOD: &str = r#"mod controller;
mod module;

pub use controller::HelloController;
pub use module::HelloHttpModule;
"#;

pub const HELLO_HTTP_MODULE: &str = r#"use nest_rs_core::module;

use super::controller::HelloController;
use crate::hello::HelloModule;

#[module(
    imports = [HelloModule],
    providers = [HelloController],
)]
pub struct HelloHttpModule;
"#;

pub const HELLO_HTTP_CONTROLLER: &str = r#"use std::sync::Arc;

use nest_rs_http::{controller, routes};

use crate::hello::HelloService;

#[controller(path = "/")]
pub struct HelloController {
    #[inject]
    svc: Arc<HelloService>,
}

#[routes]
impl HelloController {
    #[get("/")]
    async fn hello(&self) -> String {
        self.svc.greeting()
    }
}
"#;

/// Thin workspace app — composition only (`apps/platform-api` shape).
pub const APP_CARGO: &str = r#"[package]
name = "{{kebab}}"
version.workspace = true
edition.workspace = true
publish = false

[dependencies]
features.workspace = true
nest-rs-core.workspace = true
nest-rs-config.workspace = true
nest-rs-http.workspace = true
nest-rs-opentelemetry = { workspace = true, features = ["http"] }
tokio.workspace = true
anyhow.workspace = true

[dev-dependencies]
nest-rs-testing = { workspace = true, features = ["opentelemetry"] }
"#;

pub const APP_LIB: &str = r#"mod module;

pub use module::{{module}};
"#;

pub const APP_MAIN: &str = r#"use anyhow::Result;
use nest_rs_config::Environment;
use nest_rs_core::App;
use nest_rs_opentelemetry::OpenTelemetry;

use {{snake}}::{{module}};

#[tokio::main]
async fn main() -> Result<()> {
    let _environment = Environment::init();
    let _telemetry = OpenTelemetry::init("{{kebab}}")?;

    App::builder()
        .module::<{{module}}>()
        .build()
        .await?
        .run()
        .await
}
"#;

pub const APP_MODULE_WITH_HELLO: &str = r#"use nest_rs_core::module;
use nest_rs_http::{HttpConfig, HttpModule};
use nest_rs_opentelemetry::OpenTelemetryModule;

use features::hello::HelloHttpModule;

#[module(
    imports = [
        OpenTelemetryModule,
        HelloHttpModule,
        HttpModule::for_root(HttpConfig { port: {{port}}, ..Default::default() }),
    ],
)]
pub struct {{module}};
"#;

/// Thin workspace app — composition only; HTTP port pinned in code (see `apps/platform-api`).
pub const APP_MODULE: &str = r#"use nest_rs_core::module;
use nest_rs_http::{HttpConfig, HttpModule};
use nest_rs_opentelemetry::OpenTelemetryModule;

#[module(imports = [
    OpenTelemetryModule,
    HttpModule::for_root(HttpConfig { port: {{port}}, ..Default::default() }),
])]
pub struct {{module}};
"#;

pub const APP_E2E: &str = r#"use {{snake}}::{{module}};
use nest_rs_testing::TestApp;

#[tokio::test]
async fn hello_endpoint_greets() {
    let app = TestApp::builder()
        .with_test_telemetry()
        .module::<{{module}}>()
        .build()
        .await
        .expect("{{module}} boots and mounts its routes");

    let resp = app.http().get("/").send().await;
    resp.assert_status_is_ok();
    resp.assert_text("Hello World").await;
}
"#;

pub const README: &str = r#"# {{kebab}}

**Workspace** NestRS monorepo — product logic in `crates/features/`, thin
composition apps under `apps/`. Generated by `nestrs new {{kebab}}`.

## Run the default app

```bash
just dev hello
just build              # default app → target/release/hello
just build billing      # one app by name
just build-all          # every app
```

Open **http://localhost:3000/** in your browser — `Hello World` from
`crates/features/src/hello/`. `apps/hello/` only wires modules; the listen
port is set in `apps/hello/src/module.rs`, not in `.env`.

Need a single crate instead? Use
[standalone mode](/cli/#layout-detection): `nestrs new <name> --standalone`.

## Grow the workspace

```bash
nestrs new billing
nestrs g resource posts
```

Import edge modules in each app's root `module.rs` — see
[`users/`](https://github.com/NestRS/NestRS/tree/main/crates/features/src/users)
in the framework repo.
"#;

pub const JUSTFILE: &str = r#"_default:
    @just --list

# Run an app (default: hello). Usage: just dev billing
dev app="hello":
    cargo run --bin {{app}}

# Run an app in release mode.
run app="hello":
    cargo run --release --bin {{app}}

# Build one app in release (default: hello). Usage: just build billing
build app="hello":
    cargo build --release -p {{app}}

# Build release binaries for every app in the workspace.
build-all:
    cargo build --workspace --release

# Type-check the workspace.
check:
    cargo check --workspace

# Run workspace tests.
test:
    cargo test --workspace

# Apply rustfmt across the workspace.
fmt:
    cargo fmt --all

# Clippy (strict) + format check.
lint:
    cargo clippy --workspace --all-targets -- -D warnings
    cargo fmt --all --check
"#;