feat: add initial kdl setup
This commit is contained in:
parent
c3fea75178
commit
a4565c7c12
144
Cargo.lock
generated
144
Cargo.lock
generated
@ -236,6 +236,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"dotenvy",
|
||||
"kdl",
|
||||
"rusty-s3",
|
||||
"serde",
|
||||
"tokio",
|
||||
@ -448,6 +449,18 @@ version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||
|
||||
[[package]]
|
||||
name = "kdl"
|
||||
version = "6.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "412e2cf22cb560469db5b211c594ff9dcd490c6964e284ea64eddffe41c2249c"
|
||||
dependencies = [
|
||||
"miette",
|
||||
"num",
|
||||
"thiserror",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
@ -498,6 +511,29 @@ version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "miette"
|
||||
version = "7.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a955165f87b37fd1862df2a59547ac542c77ef6d17c666f619d1ad22dd89484"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"miette-derive",
|
||||
"thiserror",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miette-derive"
|
||||
version = "7.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf45bf44ab49be92fd1227a3be6fc6f617f1a337c06af54981048574d8783147"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.3"
|
||||
@ -528,12 +564,85 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
@ -787,6 +896,26 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.8"
|
||||
@ -937,6 +1066,12 @@ version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.4"
|
||||
@ -1106,6 +1241,15 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.33.0"
|
||||
|
@ -15,3 +15,4 @@ uuid.workspace = true
|
||||
|
||||
rusty-s3 = "0.7.0"
|
||||
url = "2.5.4"
|
||||
kdl = "6.3.3"
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::net::SocketAddr;
|
||||
use std::{net::SocketAddr, path::PathBuf};
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use kdl::{KdlDocument, KdlNode, KdlValue};
|
||||
use rusty_s3::{Bucket, Credentials, S3Action};
|
||||
|
||||
use crate::state::SharedState;
|
||||
@ -14,6 +15,15 @@ struct Command {
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
Init {
|
||||
#[arg(
|
||||
env = "FOREST_PROJECT_PATH",
|
||||
long = "project-path",
|
||||
default_value = "."
|
||||
)]
|
||||
project_path: PathBuf,
|
||||
},
|
||||
|
||||
Serve {
|
||||
#[arg(env = "FOREST_HOST", long, default_value = "127.0.0.1:3000")]
|
||||
host: SocketAddr,
|
||||
@ -35,32 +45,124 @@ enum Commands {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ProjectPlan {
|
||||
Local { path: PathBuf },
|
||||
NoPlan,
|
||||
}
|
||||
|
||||
impl TryFrom<&KdlNode> for ProjectPlan {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: &KdlNode) -> Result<Self, Self::Error> {
|
||||
let Some(children) = value.children() else {
|
||||
return Ok(Self::NoPlan);
|
||||
};
|
||||
|
||||
if let Some(local) = children.get_arg("local") {
|
||||
return Ok(Self::Local {
|
||||
path: local
|
||||
.as_string()
|
||||
.map(|l| l.to_string())
|
||||
.ok_or(anyhow::anyhow!("local must have an arg with a valid path"))?
|
||||
.into(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Self::NoPlan)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Project {
|
||||
name: String,
|
||||
description: Option<String>,
|
||||
plan: Option<ProjectPlan>,
|
||||
}
|
||||
|
||||
impl TryFrom<KdlDocument> for Project {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: KdlDocument) -> Result<Self, Self::Error> {
|
||||
let project_section = value.get("project").ok_or(anyhow::anyhow!(
|
||||
"forest.kdl project file must have a project object"
|
||||
))?;
|
||||
|
||||
let project_children = project_section
|
||||
.children()
|
||||
.ok_or(anyhow::anyhow!("a forest project must have children"))?;
|
||||
|
||||
let project_plan: Option<ProjectPlan> = if let Some(project) = project_children.get("plan")
|
||||
{
|
||||
Some(project.try_into()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
name: project_children
|
||||
.get_arg("name")
|
||||
.and_then(|n| match n {
|
||||
KdlValue::String(s) => Some(s),
|
||||
_ => None,
|
||||
})
|
||||
.cloned()
|
||||
.ok_or(anyhow::anyhow!("a forest kuddle project must have a name"))?,
|
||||
description: project_children
|
||||
.get_arg("description")
|
||||
.and_then(|n| match n {
|
||||
KdlValue::String(s) => Some(s.trim().to_string()),
|
||||
_ => None,
|
||||
}),
|
||||
plan: project_plan,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn execute() -> anyhow::Result<()> {
|
||||
let cli = Command::parse();
|
||||
|
||||
if let Some(Commands::Serve {
|
||||
host,
|
||||
s3_endpoint,
|
||||
s3_bucket,
|
||||
s3_region,
|
||||
s3_user,
|
||||
s3_password,
|
||||
}) = cli.command
|
||||
{
|
||||
tracing::info!("Starting server");
|
||||
match cli.command.unwrap() {
|
||||
Commands::Init { project_path } => {
|
||||
tracing::info!("initializing project");
|
||||
|
||||
let creds = Credentials::new(s3_user, s3_password);
|
||||
let bucket = Bucket::new(
|
||||
url::Url::parse(&s3_endpoint)?,
|
||||
rusty_s3::UrlStyle::Path,
|
||||
let project_file_path = project_path.join("forest.kdl");
|
||||
if !project_file_path.exists() {
|
||||
anyhow::bail!(
|
||||
"no 'forest.kdl' file was found at: {}",
|
||||
project_file_path.display().to_string()
|
||||
);
|
||||
}
|
||||
|
||||
let project_file = tokio::fs::read_to_string(project_file_path).await?;
|
||||
let project_doc: KdlDocument = project_file.parse()?;
|
||||
|
||||
let project: Project = project_doc.try_into()?;
|
||||
|
||||
tracing::trace!("found a project name: {}, {:?}", project.name, project);
|
||||
}
|
||||
|
||||
Commands::Serve {
|
||||
host,
|
||||
s3_endpoint,
|
||||
s3_bucket,
|
||||
s3_region,
|
||||
)?;
|
||||
|
||||
let put_object = bucket.put_object(Some(&creds), "some-object");
|
||||
let _url = put_object.sign(std::time::Duration::from_secs(30));
|
||||
|
||||
let _state = SharedState::new().await?;
|
||||
s3_user,
|
||||
s3_password,
|
||||
} => {
|
||||
tracing::info!("Starting server");
|
||||
let creds = Credentials::new(s3_user, s3_password);
|
||||
let bucket = Bucket::new(
|
||||
url::Url::parse(&s3_endpoint)?,
|
||||
rusty_s3::UrlStyle::Path,
|
||||
s3_bucket,
|
||||
s3_region,
|
||||
)?;
|
||||
let put_object = bucket.put_object(Some(&creds), "some-object");
|
||||
let _url = put_object.sign(std::time::Duration::from_secs(30));
|
||||
let _state = SharedState::new().await?;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
10
examples/project/forest.kdl
Normal file
10
examples/project/forest.kdl
Normal file
@ -0,0 +1,10 @@
|
||||
project {
|
||||
name local
|
||||
description """
|
||||
A simple local project that depends on ../plan for its utility scripts
|
||||
"""
|
||||
|
||||
plan {
|
||||
local "../plan"
|
||||
}
|
||||
}
|
@ -10,10 +10,25 @@
|
||||
"state": "not-done"
|
||||
},
|
||||
"projects": {
|
||||
"type": "item",
|
||||
"title": "projects",
|
||||
"description": "",
|
||||
"state": "not-done"
|
||||
"type": "section",
|
||||
"should be able to download a remote plan": {
|
||||
"type": "item",
|
||||
"title": "should be able to download a remote plan",
|
||||
"description": "",
|
||||
"state": "not-done"
|
||||
},
|
||||
"should be able to template from a remote plan": {
|
||||
"type": "item",
|
||||
"title": "should be able to template from a remote plan",
|
||||
"description": "",
|
||||
"state": "not-done"
|
||||
},
|
||||
"should be able to use scripts from a remote plan": {
|
||||
"type": "item",
|
||||
"title": "should be able to use scripts from a remote plan",
|
||||
"description": "",
|
||||
"state": "not-done"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
todos/hyperlog/graph.lock
Normal file
1
todos/hyperlog/graph.lock
Normal file
@ -0,0 +1 @@
|
||||
hyperlog-lock
|
Loading…
x
Reference in New Issue
Block a user