Skip to content

Index

repo_scaffold.add_package

Add-package helpers for repo-scaffold add-package.

Three layers, split across this package:

  • :mod:repo_scaffold.add_package.config — ProjectType enum, AddPackageConfig dataclass, and detect_project_type for auto-detecting the workspace type from manifest files.
  • :mod:repo_scaffold.add_package.workspace — add_rust_package and add_uv_package implement the per-type skeleton creation, cog.toml update, and workspace verification.
  • this module — add_package orchestrates detection and delegation.

AddPackageConfig dataclass

AddPackageConfig(
    project_path: Path, name: str, project_type: ProjectType
)

Resolved configuration for one add-package invocation.

ProjectType

Bases: Enum

Supported workspace project types.

add_package

add_package(project_path: Path, name: str) -> None

Detect the project type and delegate to the appropriate add-package logic.

PARAMETER DESCRIPTION
project_path

Root directory of the workspace project.

TYPE: Path

name

Name of the new package/crate to add.

TYPE: str

RAISES DESCRIPTION
ClickException

When no workspace is detected or the package directory already exists.

Source code in repo_scaffold/add_package/__init__.py
def add_package(project_path: Path, name: str) -> None:
    """Detect the project type and delegate to the appropriate add-package logic.

    Args:
        project_path: Root directory of the workspace project.
        name: Name of the new package/crate to add.

    Raises:
        click.ClickException: When no workspace is detected or the package
            directory already exists.
    """
    project_type = detect_project_type(project_path)
    config = AddPackageConfig(
        project_path=project_path,
        name=name,
        project_type=project_type,
    )
    if project_type == ProjectType.RUST_WORKSPACE:
        add_rust_package(config)
    elif project_type == ProjectType.PNPM_WORKSPACE:
        add_pnpm_package(config)
    else:
        add_uv_package(config)

add_pnpm_package

add_pnpm_package(config: AddPackageConfig) -> None

Add a new package to a pnpm workspace.

Steps
  1. Validate packages/<name> does not already exist.
  2. Create packages/<name>/package.json, vite.config.ts, tsconfig.json, and src/index.ts.
  3. Append a [packages.<name>] section to cog.toml.
  4. Run pnpm install to update the lockfile.
Source code in repo_scaffold/add_package/workspace.py
def add_pnpm_package(config: AddPackageConfig) -> None:
    """Add a new package to a pnpm workspace.

    Steps:
      1. Validate ``packages/<name>`` does not already exist.
      2. Create ``packages/<name>/package.json``, ``vite.config.ts``,
         ``tsconfig.json``, and ``src/index.ts``.
      3. Append a ``[packages.<name>]`` section to ``cog.toml``.
      4. Run ``pnpm install`` to update the lockfile.
    """
    name = config.name
    project_path = config.project_path
    pkg_dir = project_path / "packages" / name

    if pkg_dir.exists():
        raise click.ClickException(f"❌ {pkg_dir.relative_to(project_path)} already exists")

    # 1. Create package skeleton
    click.echo(f"Creating package '{name}' …")
    pkg_dir.mkdir(parents=True, exist_ok=True)
    src_dir = pkg_dir / "src"
    src_dir.mkdir(exist_ok=True)

    (pkg_dir / "package.json").write_text(_PNPM_PACKAGE_JSON_TEMPLATE.format(name=name), encoding="utf-8")
    (pkg_dir / "vite.config.ts").write_text(_PNPM_VITE_CONFIG_TEMPLATE.format(name=name), encoding="utf-8")
    (pkg_dir / "tsconfig.json").write_text(_PNPM_TSCONFIG_TEMPLATE.format(), encoding="utf-8")
    (src_dir / "index.ts").write_text(_PNPM_INDEX_TS_TEMPLATE.format(name=name), encoding="utf-8")

    # 2. Append cog.toml section
    _append_cog_section(project_path, name, _PNPM_COG_SECTION_TEMPLATE)

    # 3. Sync workspace
    click.echo("Syncing workspace …")
    subprocess.check_call(
        ["pnpm", "install"],
        cwd=str(project_path),
    )

    click.echo(f"✅ Package '{name}' added.")

add_rust_package

add_rust_package(config: AddPackageConfig) -> None

Add a new crate to a cargo workspace.

Steps
  1. Validate packages/<name> does not already exist.
  2. Create packages/<name>/Cargo.toml and src/lib.rs.
  3. Append a [packages.<name>] section to cog.toml.
  4. Run cargo check to verify the workspace compiles.
Source code in repo_scaffold/add_package/workspace.py
def add_rust_package(config: AddPackageConfig) -> None:
    """Add a new crate to a cargo workspace.

    Steps:
      1. Validate ``packages/<name>`` does not already exist.
      2. Create ``packages/<name>/Cargo.toml`` and ``src/lib.rs``.
      3. Append a ``[packages.<name>]`` section to ``cog.toml``.
      4. Run ``cargo check`` to verify the workspace compiles.
    """
    name = config.name
    project_path = config.project_path
    pkg_dir = project_path / "packages" / name

    if pkg_dir.exists():
        raise click.ClickException(f"❌ {pkg_dir.relative_to(project_path)} already exists")

    # 1. Create package skeleton
    click.echo(f"Creating crate '{name}' …")
    pkg_dir.mkdir(parents=True, exist_ok=True)
    src_dir = pkg_dir / "src"
    src_dir.mkdir(exist_ok=True)

    # Write Cargo.toml
    cargo_toml = pkg_dir / "Cargo.toml"
    cargo_toml.write_text(_CARGO_TOML_TEMPLATE.format(name=name), encoding="utf-8")

    # Write src/lib.rs
    lib_rs = src_dir / "lib.rs"
    lib_rs.write_text(_LIB_RS_TEMPLATE.format(name=name), encoding="utf-8")

    # 2. Append cog.toml section
    _append_cog_section(project_path, name, _RUST_COG_SECTION_TEMPLATE)

    # 3. Verify workspace compiles
    click.echo("Checking workspace …")
    result = subprocess.run(
        ["cargo", "check"],
        cwd=str(project_path),
        capture_output=True,
        text=True,
    )
    if result.returncode != 0:
        click.echo(f"⚠️  cargo check failed:\n{result.stderr}")
    else:
        click.echo(f"✅ Crate '{name}' added.")

    click.echo("\nNext steps:")
    click.echo(f"  1. Add dependencies to packages/{name}/Cargo.toml")
    click.echo(f"  2. Implement your domain in packages/{name}/src/")
    click.echo("  3. Register routes in packages/api-server/src/app.rs")

add_uv_package

add_uv_package(config: AddPackageConfig) -> None

Add a new package to a uv workspace.

Steps
  1. Validate packages/<name> does not already exist.
  2. Run uv init --lib to create the package skeleton.
  3. Append a [packages.<name>] section to cog.toml.
  4. Run uv sync --all-packages --all-groups to update the lockfile.
Source code in repo_scaffold/add_package/workspace.py
def add_uv_package(config: AddPackageConfig) -> None:
    """Add a new package to a uv workspace.

    Steps:
      1. Validate ``packages/<name>`` does not already exist.
      2. Run ``uv init --lib`` to create the package skeleton.
      3. Append a ``[packages.<name>]`` section to ``cog.toml``.
      4. Run ``uv sync --all-packages --all-groups`` to update the lockfile.
    """
    name = config.name
    project_path = config.project_path
    pkg_dir = project_path / "packages" / name

    if pkg_dir.exists():
        raise click.ClickException(f"❌ {pkg_dir.relative_to(project_path)} already exists")

    # 1. Create package skeleton via uv
    click.echo(f"Creating package '{name}' …")
    subprocess.check_call(
        ["uv", "init", "--lib", "--name", name, str(pkg_dir)],
        cwd=str(project_path),
    )

    # 2. Append cog.toml section
    _append_cog_section(project_path, name, _UV_COG_SECTION_TEMPLATE)

    # 3. Sync workspace
    click.echo("Syncing workspace …")
    subprocess.check_call(
        ["uv", "sync", "--all-packages", "--all-groups"],
        cwd=str(project_path),
    )

    module = name.replace("-", "_")
    click.echo(f"✅ Package '{name}' added. Module import name: {module}")

detect_project_type

detect_project_type(project_path: Path) -> ProjectType

Detect the workspace type from manifest files.

Resolution order
  1. Cargo.toml with a [workspace] section → RUST_WORKSPACE
  2. pyproject.toml with a [tool.uv.workspace] section → UV_WORKSPACE
  3. pnpm-workspace.yaml → PNPM_WORKSPACE
  4. None of the above → raise click.ClickException
PARAMETER DESCRIPTION
project_path

Root directory of the workspace project.

TYPE: Path

RETURNS DESCRIPTION
ProjectType

The detected ProjectType.

RAISES DESCRIPTION
ClickException

When no recognised workspace manifest is found.

Source code in repo_scaffold/add_package/config.py
def detect_project_type(project_path: Path) -> ProjectType:
    """Detect the workspace type from manifest files.

    Resolution order:
      1. ``Cargo.toml`` with a ``[workspace]`` section → ``RUST_WORKSPACE``
      2. ``pyproject.toml`` with a ``[tool.uv.workspace]`` section → ``UV_WORKSPACE``
      3. ``pnpm-workspace.yaml`` → ``PNPM_WORKSPACE``
      4. None of the above → raise ``click.ClickException``

    Args:
        project_path: Root directory of the workspace project.

    Returns:
        The detected ``ProjectType``.

    Raises:
        click.ClickException: When no recognised workspace manifest is found.
    """
    project_path = project_path.resolve()

    cargo_toml = project_path / "Cargo.toml"
    if cargo_toml.is_file():
        with cargo_toml.open("rb") as f:
            data = tomllib.load(f)
        if "workspace" in data:
            return ProjectType.RUST_WORKSPACE

    pyproject_toml = project_path / "pyproject.toml"
    if pyproject_toml.is_file():
        with pyproject_toml.open("rb") as f:
            data = tomllib.load(f)
        if "uv" in data.get("tool", {}) and "workspace" in data["tool"]["uv"]:
            return ProjectType.UV_WORKSPACE

    pnpm_workspace = project_path / "pnpm-workspace.yaml"
    if pnpm_workspace.is_file():
        return ProjectType.PNPM_WORKSPACE

    raise click.ClickException(
        "No workspace detected. Expected a Cargo.toml with [workspace], "
        "a pyproject.toml with [tool.uv.workspace], or a pnpm-workspace.yaml."
    )