1use serde::{Deserialize, Serialize};
2use tatara_lisp::DeriveTataraDomain;
3
4#[derive(DeriveTataraDomain, Serialize, Deserialize, Debug, Clone, PartialEq)]
6#[serde(rename_all = "camelCase")]
7#[tatara(keyword = "defflake")]
8pub struct FlakeLisp {
9 pub descricao: String,
10 #[serde(default)]
11 pub entradas: Vec<FlakeInput>,
12 #[serde(default)]
13 pub saidas: Option<FlakeOutput>,
14}
15
16#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
17#[serde(rename_all = "camelCase")]
18pub struct FlakeInput {
19 pub nome: String,
20 pub url: String,
21 #[serde(default, skip_serializing_if = "Option::is_none")]
23 pub segue: Option<String>,
24}
25
26#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
27#[serde(rename_all = "camelCase")]
28pub struct FlakeOutput {
29 #[serde(default)]
30 pub pacotes: Vec<FlakePackage>,
31 #[serde(default)]
32 pub modulos: Vec<FlakeModule>,
33 #[serde(default)]
34 pub dev_shells: bool,
35}
36
37#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
38#[serde(rename_all = "camelCase")]
39pub struct FlakePackage {
40 pub nome: String,
41 pub src: String,
42}
43
44#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
45#[serde(rename_all = "camelCase")]
46pub struct FlakeModule {
47 pub nome: String,
48 pub caminho: String,
49}
50
51impl FlakeLisp {
52 pub fn from_lisp(src: &str) -> Result<Self, tatara_lisp::LispError> {
53 use tatara_lisp::domain::TataraDomain;
54 let forms = tatara_lisp::read(src)?;
55 let first = forms
56 .first()
57 .ok_or_else(|| tatara_lisp::LispError::Compile {
58 form: "defflake".into(),
59 message: "empty flake.lisp".into(),
60 })?;
61 Self::compile_from_sexp(first)
62 }
63
64 pub fn register() -> Result<(), tatara_lisp::KeywordCollision> {
78 tatara_lisp::domain::register::<Self>()
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn parses_minimal_flake() {
88 let src = r#"
89(defflake
90 :descricao "my caixa"
91 :entradas ((:nome "nixpkgs" :url "github:nixos/nixpkgs?ref=nixos-unstable")
92 (:nome "substrate" :url "github:pleme-io/substrate")))
93"#;
94 let f = FlakeLisp::from_lisp(src).unwrap();
95 assert_eq!(f.descricao, "my caixa");
96 assert_eq!(f.entradas.len(), 2);
97 assert_eq!(f.entradas[0].nome, "nixpkgs");
98 }
99
100 #[test]
101 fn register_populates_registry() {
102 FlakeLisp::register().expect("first register call in this test process must succeed");
103 assert!(tatara_lisp::domain::registered_keywords().contains(&"defflake"));
104 }
105}