nest-rs-cli 0.1.0

Scaffolding CLI for nestrs — new projects, feature generators, and project health checks.
//! **Standalone mode** — one Cargo crate, all logic under `src/`.
//!
//! Generated by `nestrs new <name> --standalone`.
//! Contrasts with [`super::workspace`] (monorepo + `crates/features/`).

pub const CARGO: &str = r#"[package]
name = "{{kebab}}"
version = "0.1.0"
edition = "2024"
rust-version = "1.95"

# Own workspace root — scaffold works even inside another repo's tree.
[workspace]

[dependencies]
anyhow = "1"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
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"] }
poem = { version = "3", features = ["tower-compat", "anyhow", "rustls"] }

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

pub const 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 LIB_HELLO: &str = r#"mod controller;
mod module;
mod service;

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

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

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

pub const MODULE_HELLO: &str = r#"use nest_rs_core::module;
use nest_rs_http::HttpModule;
use nest_rs_opentelemetry::OpenTelemetryModule;

use crate::controller::{{controller}};
use crate::service::{{service}};

#[module(
    imports = [
        OpenTelemetryModule,
        HttpModule::for_root(None),
    ],
    providers = [{{service}}, {{controller}}],
)]
pub struct {{module}};
"#;

pub const MODULE_EMPTY: &str = r#"use nest_rs_core::module;
use nest_rs_http::HttpModule;
use nest_rs_opentelemetry::OpenTelemetryModule;

#[module(imports = [
    OpenTelemetryModule,
    HttpModule::for_root(None),
])]
pub struct {{module}};
"#;

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

#[injectable]
#[derive(Default)]
pub struct {{service}};

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

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

use nest_rs_http::{controller, routes};

use crate::service::{{service}};

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

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

pub const 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 DOCKERFILE: &str = r#"# syntax=docker/dockerfile:1.7
#
# Build:  docker build -t {{kebab}} .
# Run:    docker run --rm -p 3000:3000 {{kebab}}
#
# Multi-stage: compile in Rust slim, run on distroless nonroot.

ARG RUST_VERSION=1.95

FROM rust:${RUST_VERSION}-slim-trixie AS builder
WORKDIR /app
COPY Cargo.toml ./
COPY src ./src
RUN cargo build --release

FROM gcr.io/distroless/cc-debian13:nonroot AS runtime
COPY --from=builder /app/target/release/{{kebab}} /usr/local/bin/app
EXPOSE 3000
USER nonroot:nonroot
ENTRYPOINT ["/usr/local/bin/app"]
"#;

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

# Run the app (loads `.env` / `.env.development` from the project root).
dev:
    cargo run

# Run an optimized build.
run:
    cargo run --release

# Build the release binary (target/release/{{kebab}}).
build:
    cargo build --release

# Type-check without codegen.
check:
    cargo check

# Run tests.
test:
    cargo test

# Apply rustfmt.
fmt:
    cargo fmt

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

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

**Standalone** NestRS app — one crate, logic in `src/`. `GET /`, HTTP only,
no auth, no database. Generated by `nestrs new {{kebab}}`.

## Run

```bash
just dev
just build    # → target/release/{{kebab}}
just run      # build + run in release
```

Open **http://localhost:3000/** in your browser — you should see `Hello World`.

Need several apps sharing product code? Scaffold a
[workspace](/cli/#layout-detection) instead:
`nestrs new <name>`.

## Configuration

Environment variables load from the [`.env` cascade`](https://nestrs.dev/configuration/).
Committed defaults live in `.env` and `.env.development`; copy `.env.example`
to `.env.local` when you add Postgres or Redis later.
"#;