radicle-schemars: Add crate for utility binary
Extracting JSON Schemas from the Radicle crate can be done via
`radicle-cli` for `radicle::profile::Config` by executing:
rad config schema
However, for other JSON Schema metadata, this is not possible.
To allow other tools to extract JSON schemas as part of their build
process, introduce a new crate that only depends on `radicle`,
`schemars`, and `serde`, with a tiny binary that will reproduce various
schemas.
This commit is contained in:
parent
fcd1acd1dd
commit
4cd0782f2e
|
|
@ -2821,6 +2821,17 @@ dependencies = [
|
|||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radicle-schemars"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"radicle",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radicle-signals"
|
||||
version = "0.11.0"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ members = [
|
|||
"radicle-remote-helper",
|
||||
"radicle-ssh",
|
||||
"radicle-tools",
|
||||
"radicle-schemars",
|
||||
"radicle-signals",
|
||||
"radicle-systemd",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "radicle-schemars"
|
||||
description = "Utility to print JSON Schemas from the `radicle` crate"
|
||||
homepage = "https://radicle.xyz"
|
||||
repository = "https://app.radicle.xyz/seeds/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5"
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
version = "0.1.0"
|
||||
rust-version.workspace = true
|
||||
|
||||
[[bin]]
|
||||
name = "radicle-schemars"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
once_cell = { version = "1.13" }
|
||||
schemars = { workspace = true }
|
||||
serde = { version = "1.0" }
|
||||
serde_json = { version = "1" }
|
||||
|
||||
[dependencies.radicle]
|
||||
version = "0"
|
||||
path = "../radicle"
|
||||
features = ["schemars"]
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
use std::io;
|
||||
use std::net;
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use schemars::{generate::*, *};
|
||||
|
||||
const SCHEMA_COMMAND: &str = "radicle::node::Command";
|
||||
const SCHEMA_COMMAND_RESULT: &str = "radicle::node::CommandResult";
|
||||
const SCHEMA_PROFILE_CONFIG: &str = "radicle::profile::Config";
|
||||
|
||||
const SCHEMAS: &[&str] = &[SCHEMA_COMMAND, SCHEMA_COMMAND_RESULT, SCHEMA_PROFILE_CONFIG];
|
||||
|
||||
pub static ERROR_MSG: Lazy<String> = Lazy::new(|| {
|
||||
let schemas = SCHEMAS.to_vec().join("\", \"");
|
||||
format!("Expected exactly one of the following schema names: [\"{schemas}\"].")
|
||||
});
|
||||
|
||||
enum Schema {
|
||||
Command,
|
||||
CommandResult,
|
||||
ProfileConfig,
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Schema {
|
||||
type Err = io::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
SCHEMA_COMMAND => Ok(Self::Command),
|
||||
SCHEMA_COMMAND_RESULT => Ok(Self::CommandResult),
|
||||
SCHEMA_PROFILE_CONFIG => Ok(Self::ProfileConfig),
|
||||
schema => Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!("{schema}: {}", *ERROR_MSG),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Schema {
|
||||
fn from_args(mut args: std::env::Args) -> io::Result<Self> {
|
||||
let name = args.nth(1).ok_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!("No schema given. {}", *ERROR_MSG),
|
||||
)
|
||||
})?;
|
||||
name.parse()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(e) = print_schema() {
|
||||
eprintln!("{}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn print_schema() -> io::Result<()> {
|
||||
let args = std::env::args();
|
||||
|
||||
let name = Schema::from_args(args)?;
|
||||
|
||||
let schema = match name {
|
||||
Schema::Command => {
|
||||
let settings = SchemaSettings::default().for_serialize();
|
||||
let generator = settings.into_generator();
|
||||
|
||||
generator.into_root_schema_for::<radicle::node::Command>()
|
||||
}
|
||||
Schema::CommandResult => {
|
||||
#[derive(JsonSchema)]
|
||||
#[allow(dead_code)]
|
||||
struct ListenAddrs(Vec<net::SocketAddr>);
|
||||
|
||||
#[derive(JsonSchema)]
|
||||
#[allow(dead_code)]
|
||||
struct Error {
|
||||
error: String,
|
||||
}
|
||||
|
||||
#[derive(JsonSchema)]
|
||||
#[schemars(untagged)]
|
||||
#[allow(dead_code)]
|
||||
enum CommandResult {
|
||||
Nid(
|
||||
#[schemars(with = "radicle::schemars_ext::crypto::PublicKey")]
|
||||
radicle::node::NodeId,
|
||||
),
|
||||
Config(radicle::node::Config),
|
||||
ListenAddrs(ListenAddrs),
|
||||
ConnectResult(radicle::node::ConnectResult),
|
||||
Success(radicle::node::Success),
|
||||
Seeds(radicle::node::Seeds),
|
||||
FetchResult(radicle::node::FetchResult),
|
||||
RefsAt(radicle::storage::refs::RefsAt),
|
||||
Sessions(Vec<radicle::node::Session>),
|
||||
Session(Option<radicle::node::Session>),
|
||||
Error(Error),
|
||||
}
|
||||
schema_for!(CommandResult)
|
||||
}
|
||||
Schema::ProfileConfig => schemars::schema_for!(radicle::profile::Config),
|
||||
};
|
||||
|
||||
serde_json::to_writer_pretty(std::io::stdout(), &schema)?;
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Reference in New Issue