pray-cli 1.17.0

Package manager for the language placed before inference — Prayfile CLI (binary: pray)
use crate::commands_init_prayer_manifest::{declare_local_prayer, resolve_local_prayer_directory};
use crate::project_paths::{manifest_path, workspace_root};
use pray_core::local_prayer::{validate_local_prayer_name, DEFAULT_LOCAL_PRAYER_NAME};
use pray_core::{PrayError, PrayResult};
use std::env;
use std::fs;
use std::path::Path;

pub(crate) fn prayer_init_command(
    name: Option<String>,
    directory: Option<String>,
) -> PrayResult<()> {
    if manifest_path().exists() {
        scaffold_local_prayer(name, directory)
    } else {
        scaffold_standalone_package(name)
    }
}

fn scaffold_local_prayer(name: Option<String>, directory: Option<String>) -> PrayResult<()> {
    let package_name =
        validate_local_prayer_name(name.as_deref().unwrap_or(DEFAULT_LOCAL_PRAYER_NAME))?;
    let source = resolve_local_prayer_directory(directory.as_deref())?;
    let root = workspace_root().join(&source.directory).join(package_name);
    let prayspec_path = root.join(format!("{package_name}.prayspec"));
    if prayspec_path.exists() {
        return Err(PrayError::Manifest(format!(
            "package spec already exists: {}",
            prayspec_path.display()
        )));
    }
    if root.exists() {
        return Err(PrayError::Manifest(format!(
            "prayer directory already exists: {}",
            root.display()
        )));
    }

    fs::create_dir_all(root.join("exports"))?;
    fs::write(&prayspec_path, local_prayspec(&source.name, package_name))?;
    fs::write(root.join("README.md"), format!("# {package_name}\n"))?;
    fs::write(
        root.join(format!("exports/{package_name}.md")),
        format!("# {package_name}\n"),
    )?;
    declare_local_prayer(&format!("{}/{}", source.name, package_name))
}

fn scaffold_standalone_package(name: Option<String>) -> PrayResult<()> {
    let root = env::current_dir()?;
    let package_name = match name {
        Some(value) => validate_local_prayer_name(&value)?.to_string(),
        None => root
            .file_name()
            .and_then(|value| value.to_str())
            .filter(|value| !value.trim().is_empty())
            .unwrap_or("prayer-package")
            .to_string(),
    };
    write_standalone_scaffold(&root, &package_name)
}

fn write_standalone_scaffold(root: &Path, package_name: &str) -> PrayResult<()> {
    let prayspec_path = root.join(format!("{package_name}.prayspec"));
    if prayspec_path.exists() {
        return Err(PrayError::Manifest(format!(
            "package spec already exists: {}",
            prayspec_path.display()
        )));
    }
    fs::write(&prayspec_path, standalone_prayspec(package_name))?;
    if !root.join("README.md").exists() {
        fs::write(root.join("README.md"), format!("# {package_name}\n"))?;
    }
    fs::create_dir_all(root.join("exports"))?;
    Ok(())
}

fn local_prayspec(source_name: &str, name: &str) -> String {
    format!(
        r#"Package::Specification.new do |spec|
  spec.name = "{source_name}/{name}"
  spec.summary = "Describe this package"
  spec.files = ["README.md", "exports/{name}.md"]
  spec.exports = {{
    "{name}" => {{
      type: "fragment",
      path: "exports/{name}.md"
    }}
  }}
end
"#
    )
}

fn standalone_prayspec(name: &str) -> String {
    format!(
        r#"Package::Specification.new do |spec|
  spec.name = "{name}"
  spec.version = "0.1.0"
  spec.summary = "Describe this package"
  spec.files = ["README.md"]
  spec.exports = {{}}
end
"#
    )
}