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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "star-setup"
version = "0.4.4"
version = "0.4.5"
edition = "2021"
repository = "https://github.com/star-setup/core"
description = "Lightweight CLI to clone, configure, and wire single or multi-repo ecosystems"
Expand Down
61 changes: 37 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ star-setup username/repo --repos user/lib1 user/lib2
- npm (Node.js 22+)

## Installation
Download the latest binary from [Releases](https://github.com/star-setup/core/releases), or use one of the methods below.

Download the latest binary from [Releases](https://github.com/star-setup/core/releases), or:
<details><summary>Show installation methods</summary>

### Homebrew (macOS/Linux)
```bash
Expand Down Expand Up @@ -64,6 +65,7 @@ Download the `.msi` from [Releases](https://github.com/star-setup/core/releases)
```bash
cargo install --git https://github.com/star-setup/core
```
</details>

## Usage

Expand All @@ -86,7 +88,8 @@ cargo install --git https://github.com/star-setup/core
| `--meson-arg <ARG>` | Pass additional argument to Meson |
| `--watch` | Generate and open watch scripts (npm mono-repo mode) |
| `--no-watch` | Skip generating watch scripts (npm mono-repo mode) |

| `--dev` | Automatically start the dev server (npm) |
| `--no-dev` | Skip opening the dev server (npm) |

#### Mono-Repo
| Flag | Description |
Expand Down Expand Up @@ -123,13 +126,13 @@ Interactive mode complete
```

### Single Repository Mode
Build system is auto-detected from the repository root (`CMakeLists.txt` → CMake, `meson.build` → Meson, `package.json` → npm). Pass `--dev` to launch the project's dev server after setup.

```bash
# Clone and build using a single repository
star-setup username/repo
```

Build system is auto-detected from the repository root (`CMakeLists.txt` → CMake, `meson.build` → Meson, `package.json` → npm).

### Mono-Repo Mode
Clones multiple repositories into a single workspace and auto-detects the build system.

Expand All @@ -141,7 +144,9 @@ star-setup username/repo --repos user/lib1 user/lib2
star-setup username/repo --profile myprofile
```

#### Workspace Structure (CMake)
#### Workspace Structures
<details><summary>CMake</summary>

Generates a root `CMakeLists.txt` wiring all repositories as subdirectories

```
Expand All @@ -167,7 +172,10 @@ endif()
```
This allows the same repository to work both standalone (fetching dependencies automatically) and inside a mono-repo workspace (linking locally for full cross-module debugging).

#### Workspace Structure (Meson)
</details>

<details><summary>Meson</summary>

Generates a root `meson.build` and auto-generates local `.wrap` files bridging canonical dependency names to cloned directories.

```
Expand All @@ -182,7 +190,10 @@ build-mono/
└── build/ # Build output
```

#### Workspace Structure (Npm)
</details>

<details><summary>Npm</summary>

Generates a workspace root `package.json` that wires all cloned repositories together using npm workspaces and forces local resolution via `overrides` — no changes to individual repository files. Each lib's `package.json` is read after cloning to extract its package name for the overrides map.

```
Expand All @@ -209,12 +220,14 @@ star-setup username/repo --repos user/lib1 user/lib2
star-setup username/repo --repos user/lib1 user/lib2 --no-watch
```

After setup, run the game from its repo directory:
After setup pass `--dev` to launch it automatically, or run the game from its repo directory:
```bash
cd build-mono/repos/user-my-repo
npm run dev
```

</details>

#### Workspace Mode
Manage an existing mono-repo workspace.

Expand All @@ -239,22 +252,6 @@ Workspace flags:
| `--mono-dir <DIR>` | Workspace directory name (default: `build-mono`) |
| `--build-dir <DIR>` | Build directory name (default: `build`) |

### Profile Mode
Profiles represent a saved ecosystem of libraries commonly used together.
```bash
# Add a profile
star-setup profile add myprofile user/lib1 user/lib2

# List profiles
star-setup profile list

# Remove a profile
star-setup profile remove myprofile

# Use a profile
star-setup username/repo --profile myprofile
```

### Config Mode
Config files are checked in this order:
- `./.star-setup.json` (current directory)
Expand All @@ -277,6 +274,22 @@ star-setup config remove myconfig
star-setup username/repo --config myconfig
```

### Profile Mode
Profiles represent a saved ecosystem of libraries commonly used together.
```bash
# Add a profile
star-setup profile add myprofile user/lib1 user/lib2

# List profiles
star-setup profile list

# Remove a profile
star-setup profile remove myprofile

# Use a profile
star-setup username/repo --profile myprofile
```

### Development
```bash
git clone https://github.com/star-setup/core
Expand Down
15 changes: 11 additions & 4 deletions src/cli/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,19 @@ pub struct BuildFlags {
#[arg(long = "meson-arg", action = Append)]
pub meson_flags: Vec<String>,

/// Automatically open watch scripts for npm mono-repo mode.
#[arg(long)]
/// Automatically open watch scripts for libraries if applicable.
#[arg(long, conflicts_with = "no_watch")]
pub watch: bool,
/// Skip generating watch scripts for npm mono-repo mode.
#[arg(long)]
/// Skip generating watch scripts. (overrides config)
#[arg(long, conflicts_with = "watch")]
pub no_watch: bool,

/// Automatically open dev server.
#[arg(long, conflicts_with = "no_dev")]
pub dev: bool,
/// Skip opening the dev server. (overrides config)
#[arg(long, conflicts_with = "dev")]
pub no_dev: bool,
}

#[derive(ClapArgs)]
Expand Down
27 changes: 25 additions & 2 deletions src/cli/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ pub fn resolve_bool(positive: bool, negative: bool, config: Option<bool>, defaul
}
}

/// Resolves a positive/negative flag pair, each using the other as its negation.
fn resolve_flag_pair(
pos: bool,
neg: bool,
cfg_pos: Option<bool>,
cfg_neg: Option<bool>,
) -> (bool, bool) {
(
resolve_bool(pos, neg, cfg_pos, false),
resolve_bool(neg, pos, cfg_neg, false),
)
}

/// Resolves raw `Args` into `ResolvedArgs` by applying config defaults and CLI overrides.
/// # Errors
/// Returns an error if the named config does not exist in the provided `SetupConfig`.
Expand Down Expand Up @@ -69,6 +82,14 @@ pub fn resolve_with_config(mut args: Args, config: &SetupConfig) -> Result<Resol
default.map(|e| e.clean),
false,
);
let (watch, no_watch) = resolve_flag_pair(
args.build.watch, args.build.no_watch,
default.map(|e| e.watch), default.map(|e| e.no_watch),
);
let (dev, no_dev) = resolve_flag_pair(
args.build.dev, args.build.no_dev,
default.map(|e| e.dev), default.map(|e| e.no_dev),
);

let cmake_flags = Some(args.build.cmake_flags)
.filter(|f| !f.is_empty())
Expand Down Expand Up @@ -104,10 +125,12 @@ pub fn resolve_with_config(mut args: Args, config: &SetupConfig) -> Result<Resol
build_system: args.build.build_system,
no_build,
clean,
watch,
no_watch,
dev,
no_dev,
cmake_flags,
meson_flags,
watch: args.build.watch,
no_watch: args.build.no_watch,
},
mono: ResolvedMonoFlags {
mono_repo,
Expand Down
6 changes: 4 additions & 2 deletions src/cli/resolved.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ pub struct ResolvedBuildFlags {
pub build_system: Option<BuildSystem>,
pub no_build: bool,
pub clean: bool,
pub cmake_flags: Vec<String>,
pub meson_flags: Vec<String>,
pub watch: bool,
pub no_watch: bool,
pub dev: bool,
pub no_dev: bool,
pub cmake_flags: Vec<String>,
pub meson_flags: Vec<String>,
}

/// Resolved mono-repo flags after applying config and CLI overrides.
Expand Down
106 changes: 106 additions & 0 deletions src/commands/dev.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#[cfg(not(target_os = "windows"))]
use crate::utils::process::resolve_exe_args;
use crate::{
cli::{
BuildSystem::{self, Npm},
ResolvedArgs,
},
commands::read_package_json,
ctx::{IoCtx, RunCtx, RunFlags},
};
use std::{
path::Path,
process::{Command, Stdio},
};

/// Returns the dev command for a repo, or `None` if it has no `dev` script.
pub fn resolve_dev_command(
repo_path: &Path,
io: &mut IoCtx<'_>,
flags: RunFlags,
) -> Option<String> {
let json = read_package_json(repo_path, "skipping dev server", io, flags)?;
if json.get("scripts").and_then(|s| s.get("dev")).is_some() {
Some("npm run dev".to_string())
} else {
if flags.verbose {
writeln!(io.output, " No dev script found, skipping dev server").ok();
}
None
}
}

/// Runs the dev server in the foreground, blocking until it exits (Ctrl-C).
/// # Errors
/// Returns an error only if the process fails to spawn.
pub fn open_dev_server(
repo_path: &Path,
cmd: &str,
io: &mut IoCtx<'_>,
flags: RunFlags,
) -> Result<(), String> {
if flags.dry_run {
writeln!(io.output, " Would start dev server: {cmd}").ok();
return Ok(());
}

writeln!(io.output, "Starting dev server: {cmd}").ok();
writeln!(
io.output,
" in {} (press Ctrl-C to stop)",
repo_path.display()
)
.ok();

#[cfg(target_os = "windows")]
let mut command = {
let mut c = Command::new("powershell");
c.args(["-NoProfile", "-Command", cmd]);
c
};
#[cfg(not(target_os = "windows"))]
let mut command = {
let parts: Vec<&str> = cmd.split_whitespace().collect();
let resolved = resolve_exe_args(&parts);
let mut c = Command::new(resolved[0]);
c.args(&resolved[1..]);
c
};

command
.current_dir(repo_path)
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit());

match command.spawn() {
Err(e) => Err(format!("Failed to start dev server: {e}")),
Ok(mut child) => {
child.wait().ok();
Ok(())
}
}
}

/// Opens the project's dev server if `--dev` was passed and the build system is npm.
/// # Errors
/// Returns an error only if the dev server process fails to spawn.
pub fn maybe_open_dev_server(
args: &ResolvedArgs,
build_system: Option<BuildSystem>,
repo_path: &Path,
ctx: &mut RunCtx<'_, '_>,
) -> Result<(), String> {
if !args.build.dev || build_system != Some(Npm) {
return Ok(());
}
let cmd = if ctx.flags.dry_run {
Some("npm run dev".to_string())
} else {
resolve_dev_command(repo_path, &mut ctx.io, ctx.flags)
};
if let Some(cmd) = cmd {
open_dev_server(repo_path, &cmd, &mut ctx.io, ctx.flags)?;
}
Ok(())
}
7 changes: 5 additions & 2 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ pub mod mono;
pub use mono::{
build_repo_list, create_mono_repo_cmakelists, create_mono_repo_mesonbuild,
create_mono_repo_package_json, generate_mono_config, generate_watch_scripts, hoist_wraps,
mono_repo_mode, read_package_json, resolve_repos_for_mono, resolve_setup_paths,
resolve_test_repo,
mono_repo_mode, resolve_repos_for_mono, resolve_setup_paths, resolve_test_repo,
wraps::{parse_project_name, parse_provide_pairs},
};
pub mod single;
Expand All @@ -16,3 +15,7 @@ pub mod setup;
pub use setup::{extract_repo_input, prepare_build_dir};
pub mod handlers;
pub use handlers::{handle_config_cmd, handle_profile_cmd, handle_workspace_cmd};
pub mod npm;
pub use npm::read_package_json;
pub mod dev;
pub use dev::{maybe_open_dev_server, open_dev_server, resolve_dev_command};
2 changes: 1 addition & 1 deletion src/commands/mono/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ pub fn create_mono_repo_package_json(
if i == 0 {
continue;
}
if let Some(json) = read_package_json(repos_path, dir, "skipping override", io, flags) {
if let Some(json) = read_package_json(&repos_path.join(dir), "skipping override", io, flags) {
if let Some(name) = json.get("name").and_then(|n| n.as_str()) {
overrides.push(format!(" \"{name}\": \"*\""));
}
Expand Down
2 changes: 0 additions & 2 deletions src/commands/mono/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,3 @@ pub mod setup;
pub use setup::{build_repo_list, generate_mono_config};
pub mod watch;
pub use watch::{generate_watch_scripts, open_watch_scripts};
pub mod npm;
pub use npm::read_package_json;
5 changes: 3 additions & 2 deletions src/commands/mono/mode.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
cli::{detect_mono_build_system, BuildSystem::Npm, ResolvedArgs},
commands::{
build_project, build_repo_list, extract_repo_input,
build_project, build_repo_list, extract_repo_input, maybe_open_dev_server,
mono::{
display::{resolve_setup_paths, SetupPaths},
generate_mono_config, generate_watch_scripts, open_watch_scripts, print_setup_complete,
Expand Down Expand Up @@ -133,5 +133,6 @@ pub fn mono_repo_mode(
} else {
print_setup_complete(&paths, total, &mut ctx.io, ctx.flags);
}
Ok(())

maybe_open_dev_server(args, build_system, &repo_dirs[0], ctx)
}
Loading
Loading