misc: rename to 'pgd'
This commit is contained in:
24
CLAUDE.md
24
CLAUDE.md
@@ -4,27 +4,27 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Project Overview
|
||||
|
||||
`pgx` is a CLI tool for managing project-scoped PostgreSQL instances running in Docker containers. Each project gets its own isolated Postgres instance, managed through a `pgx.toml` configuration file.
|
||||
`pgd` is a CLI tool for managing project-scoped PostgreSQL instances running in Docker containers. Each project gets its own isolated Postgres instance, managed through a `pgd.toml` configuration file.
|
||||
|
||||
## Core Architecture
|
||||
|
||||
### Project-Oriented Design
|
||||
|
||||
- Each project has a `pgx.toml` file at its root that defines the Postgres configuration
|
||||
- The project name is derived from the directory containing `pgx.toml`
|
||||
- Each project has a `pgd.toml` file at its root that defines the Postgres configuration
|
||||
- The project name is derived from the directory containing `pgd.toml`
|
||||
- Each project gets its own Docker container
|
||||
- State is tracked separately per instance to detect configuration drift
|
||||
|
||||
### Configuration Management
|
||||
|
||||
The `pgx.toml` file stores:
|
||||
The `pgd.toml` file stores:
|
||||
- `postgres_version`: PostgreSQL version to use
|
||||
- `database_name`: Name of the database
|
||||
- `user_name`: Database user
|
||||
- `password`: Database password
|
||||
- `port`: Host port to bind (auto-selected from available ports)
|
||||
|
||||
Values are auto-populated during `pgx init` with sensible defaults or random values where appropriate.
|
||||
Values are auto-populated during `pgd init` with sensible defaults or random values where appropriate.
|
||||
|
||||
### State Tracking
|
||||
|
||||
@@ -36,7 +36,7 @@ The tool maintains separate state for each instance to detect configuration drif
|
||||
## Key Dependencies
|
||||
|
||||
- **clap** (with derive feature): CLI argument parsing and command structure
|
||||
- **toml**: Parsing and serializing `pgx.toml` configuration files
|
||||
- **toml**: Parsing and serializing `pgd.toml` configuration files
|
||||
- **bollard**: Docker daemon interaction for container lifecycle management
|
||||
- **tokio** (with full feature set): Async runtime for Docker operations
|
||||
- **tracing** + **tracing-subscriber**: Structured logging throughout the application
|
||||
@@ -80,15 +80,15 @@ cargo fmt -- --check # Check without modifying
|
||||
|
||||
The CLI follows this pattern:
|
||||
```
|
||||
pgx <command> [options]
|
||||
pgd <command> [options]
|
||||
```
|
||||
|
||||
Key commands to implement:
|
||||
- `pgx init`: Create pgx.toml with auto-populated configuration
|
||||
- `pgx start`: Start the Postgres container for current project
|
||||
- `pgx stop`: Stop the running container
|
||||
- `pgx status`: Show instance status and detect drift
|
||||
- `pgx destroy`: Remove container and clean up
|
||||
- `pgd init`: Create pgd.toml with auto-populated configuration
|
||||
- `pgd start`: Start the Postgres container for current project
|
||||
- `pgd stop`: Stop the running container
|
||||
- `pgd status`: Show instance status and detect drift
|
||||
- `pgd destroy`: Remove container and clean up
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
|
||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1001,7 +1001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
|
||||
[[package]]
|
||||
name = "pgx"
|
||||
name = "pgd"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bollard",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "pgx"
|
||||
name = "pgd"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
|
||||
3
pgd.toml
Normal file
3
pgd.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
version = "18.1"
|
||||
password = "GypnQVF1uV23DWvp"
|
||||
port = 5433
|
||||
@@ -1,7 +1,7 @@
|
||||
_______ _______ __ __
|
||||
| || || |_| |
|
||||
| _ || ___|| |
|
||||
| |_| || | __ | |
|
||||
| ___|| || | | |
|
||||
| | | |_| || _ |
|
||||
|___| |_______||__| |__|
|
||||
▄▄▄▄ ▐▌
|
||||
█ █ ▐▌
|
||||
█▄▄▄▀ ▗▞▀▜▌
|
||||
█ ▗▄▖▝▚▄▟▌
|
||||
▀ ▐▌ ▐▌
|
||||
▝▀▜▌
|
||||
▐▙▄▞▘
|
||||
@@ -7,7 +7,7 @@ const STYLES: styling::Styles = styling::Styles::styled()
|
||||
.placeholder(styling::AnsiColor::Cyan.on_default());
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "pgx")]
|
||||
#[command(name = "pgd")]
|
||||
#[command(about = "Project-scoped PostgreSQL instance manager", long_about = None)]
|
||||
#[command(version)]
|
||||
#[command(styles = STYLES)]
|
||||
|
||||
@@ -35,12 +35,12 @@ impl Display for PostgresVersion {
|
||||
}
|
||||
}
|
||||
|
||||
const PROJECT_FILENAME: &str = "pgx.toml";
|
||||
const PROJECT_FILENAME: &str = "pgd.toml";
|
||||
|
||||
/// Configuration stored in pgx.toml
|
||||
/// Configuration stored in pgd.toml
|
||||
#[serde_as]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PgxConfig {
|
||||
pub struct PGDConfig {
|
||||
/// PostgreSQL version to use
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
pub version: PostgresVersion,
|
||||
@@ -52,16 +52,16 @@ pub struct PgxConfig {
|
||||
pub port: u16,
|
||||
}
|
||||
|
||||
impl PgxConfig {
|
||||
impl PGDConfig {
|
||||
pub fn load(path: impl AsRef<Path>) -> Result<Self> {
|
||||
let path = path.as_ref();
|
||||
let content = std::fs::read_to_string(path)
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| format!("Failed to read config file: {}", path.display()))?;
|
||||
|
||||
let config: PgxConfig = toml::from_str(&content)
|
||||
let config: PGDConfig = toml::from_str(&content)
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to parse pgx.toml")?;
|
||||
.wrap_err("Failed to parse pgd.toml")?;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
@@ -85,16 +85,16 @@ pub struct Project {
|
||||
/// Project name (derived from directory name)
|
||||
pub name: String,
|
||||
|
||||
/// Path to the project directory containing pgx.toml
|
||||
/// Path to the project directory containing pgd.toml
|
||||
pub path: PathBuf,
|
||||
|
||||
pub config: PgxConfig,
|
||||
pub config: PGDConfig,
|
||||
}
|
||||
|
||||
impl Project {
|
||||
pub fn container_name(&self) -> String {
|
||||
let container_name = format!(
|
||||
"pgx-{}-{}",
|
||||
"pgd-{}-{}",
|
||||
self.name,
|
||||
self.config.version.to_string().replace('.', "_")
|
||||
);
|
||||
@@ -110,7 +110,7 @@ impl Project {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let config = PgxConfig::load(&config_path)?;
|
||||
let config = PGDConfig::load(&config_path)?;
|
||||
let name = Self::extract_project_name(&project_path)?;
|
||||
|
||||
Ok(Some(Project {
|
||||
@@ -120,7 +120,7 @@ impl Project {
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn new(config: PgxConfig) -> Result<Self> {
|
||||
pub fn new(config: PGDConfig) -> Result<Self> {
|
||||
let project_path = get_project_path()?;
|
||||
let name = Self::extract_project_name(&project_path)?;
|
||||
|
||||
@@ -143,9 +143,9 @@ impl Project {
|
||||
.ok_or_else(|| miette::miette!("Failed to extract project name from path"))
|
||||
}
|
||||
|
||||
/// Get the path to the pgx.toml file
|
||||
/// Get the path to the pgd.toml file
|
||||
pub fn config_path(&self) -> PathBuf {
|
||||
self.path.join("pgx.toml")
|
||||
self.path.join("pgd.toml")
|
||||
}
|
||||
|
||||
/// Save the current configuration
|
||||
|
||||
@@ -3,7 +3,7 @@ use miette::{bail, miette};
|
||||
use miette::Result;
|
||||
|
||||
use crate::{
|
||||
config::{PgxConfig, PostgresVersion, Project},
|
||||
config::{PGDConfig, PostgresVersion, Project},
|
||||
controller::docker::DockerController,
|
||||
state::{InstanceState, StateManager},
|
||||
};
|
||||
@@ -34,7 +34,7 @@ impl Controller {
|
||||
return self.reconcile(project).await;
|
||||
}
|
||||
|
||||
println!("Initializing new pgx project...");
|
||||
println!("Initializing new pgd project...");
|
||||
|
||||
let mut versions = self.docker.available_versions().await?;
|
||||
versions.sort();
|
||||
@@ -42,14 +42,14 @@ impl Controller {
|
||||
.last()
|
||||
.ok_or(miette!("expected to have at least one version"))?;
|
||||
|
||||
let config = PgxConfig {
|
||||
let config = PGDConfig {
|
||||
version: *latest_version,
|
||||
password: utils::generate_password(),
|
||||
port: utils::find_available_port()?,
|
||||
};
|
||||
let project = Project::new(config)?;
|
||||
|
||||
println!("Created pgx.toml in {}", project.path.display());
|
||||
println!("Created pgd.toml in {}", project.path.display());
|
||||
println!(" Project: {}", project.name);
|
||||
println!(" PostgreSQL version: {}", project.config.version);
|
||||
println!(" Port: {}", project.config.port);
|
||||
|
||||
@@ -34,7 +34,7 @@ impl DockerController {
|
||||
let docker = Docker::connect_with_local_defaults()
|
||||
.into_diagnostic()
|
||||
.wrap_err(
|
||||
"Failed to connect to Docker! pgx required Docker installed. Make sure it's running.",
|
||||
"Failed to connect to Docker! pgd required Docker installed. Make sure it's running.",
|
||||
)?;
|
||||
|
||||
info!("docker.created");
|
||||
@@ -156,7 +156,7 @@ impl DockerController {
|
||||
};
|
||||
|
||||
let mut labels = HashMap::new();
|
||||
labels.insert("pgx.postgres.version".to_string(), version.to_string());
|
||||
labels.insert("pgd.postgres.version".to_string(), version.to_string());
|
||||
|
||||
let config = ContainerCreateBody {
|
||||
image: Some(image),
|
||||
@@ -255,8 +255,8 @@ impl DockerController {
|
||||
.ok_or_else(|| miette!("Container has no labels"))?;
|
||||
|
||||
let version_str = labels
|
||||
.get("pgx.postgres.version")
|
||||
.ok_or_else(|| miette!("Container missing pgx.postgres.version label"))?;
|
||||
.get("pgd.postgres.version")
|
||||
.ok_or_else(|| miette!("Container missing pgd.postgres.version label"))?;
|
||||
|
||||
PostgresVersion::from_str(version_str)
|
||||
.map_err(|_| miette!("Invalid version in label: {}", version_str))
|
||||
|
||||
@@ -23,7 +23,7 @@ async fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
init_tracing(cli.verbose);
|
||||
|
||||
info!("pgx.start");
|
||||
info!("pgd.start");
|
||||
let controller = Controller::new().await?;
|
||||
|
||||
match cli.command {
|
||||
|
||||
16
src/state.rs
16
src/state.rs
@@ -21,7 +21,7 @@ pub struct InstanceState {
|
||||
pub created_at: u64,
|
||||
}
|
||||
|
||||
/// Manages the global state file at ~/.pgx/state.json
|
||||
/// Manages the global state file at ~/.pgd/state.json
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct StateManager {
|
||||
/// Map of project name to instance state
|
||||
@@ -29,23 +29,23 @@ pub struct StateManager {
|
||||
instances: HashMap<String, InstanceState>,
|
||||
}
|
||||
|
||||
/// Get the path to the state file (~/.pgx/state.json)
|
||||
/// Get the path to the state file (~/.pgd/state.json)
|
||||
|
||||
fn state_file_path() -> Result<PathBuf> {
|
||||
let home = std::env::var("HOME")
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to get HOME environment variable")?;
|
||||
|
||||
Ok(PathBuf::from(home).join(".pgx").join("state.json"))
|
||||
Ok(PathBuf::from(home).join(".pgd").join("state.json"))
|
||||
}
|
||||
|
||||
/// Get the path to the .pgx directory
|
||||
pub fn pgx_dir() -> Result<PathBuf> {
|
||||
/// Get the path to the .pgd directory
|
||||
pub fn pgd_dir() -> Result<PathBuf> {
|
||||
let home = std::env::var("HOME")
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to get HOME environment variable")?;
|
||||
|
||||
Ok(PathBuf::from(home).join(".pgx"))
|
||||
Ok(PathBuf::from(home).join(".pgd"))
|
||||
}
|
||||
|
||||
impl StateManager {
|
||||
@@ -58,7 +58,7 @@ impl StateManager {
|
||||
if let Some(parent) = state_path.parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to create .pgx directory")?;
|
||||
.wrap_err("Failed to create .pgd directory")?;
|
||||
}
|
||||
|
||||
// Return empty state
|
||||
@@ -86,7 +86,7 @@ impl StateManager {
|
||||
if let Some(parent) = state_path.parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to create .pgx directory")?;
|
||||
.wrap_err("Failed to create .pgd directory")?;
|
||||
}
|
||||
|
||||
let content = serde_json::to_string_pretty(self)
|
||||
|
||||
Reference in New Issue
Block a user