Skip to content

Commit

Permalink
upgrade rust exporter and add Typescript::format
Browse files Browse the repository at this point in the history
  • Loading branch information
oscartbeaumont committed Dec 6, 2024
1 parent 3c5f1f9 commit bf3a093
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 36 deletions.
69 changes: 41 additions & 28 deletions specta-rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
html_favicon_url = "https://github.com/oscartbeaumont/specta/raw/main/.github/logo-128.png"
)]

use specta::{datatype::DataType, Generics, Type, TypeCollection};
use specta::{
datatype::{DataType, NamedDataType, StructFields},
Generics, Type, TypeCollection,
};

/// TODO
pub fn export<T: Type>() -> Result<String, String> {
Expand All @@ -15,7 +18,19 @@ pub fn export<T: Type>() -> Result<String, String> {
))
}

fn datatype(t: &DataType) -> Result<String, String> {
pub fn export_named_datatype(
// conf: &Typescript,
typ: &NamedDataType,
// type_map: &TypeCollection,
) -> Result<String, String> {
Ok(format!(
"pub type {} = {}",
typ.name(),
datatype(&typ.inner)?
))
}

pub fn datatype(t: &DataType) -> Result<String, String> {
// TODO: This system does lossy type conversions. That is something I want to fix in the future but for now this works. Eg. `HashSet<T>` will be exported as `Vec<T>`
// TODO: Serde serialize + deserialize on types

Expand All @@ -42,36 +57,34 @@ fn datatype(t: &DataType) -> Result<String, String> {
.join(", ")
),
},
DataType::Struct(s) => {
// match &s.fields()[..] {
// [] => "struct {name}".to_string(),
// fields => {
// let generics = (!s.generics().is_empty())
// .then(|| format!("<{}>", s.generics().join(", ")))
// .unwrap_or_default();
DataType::Struct(s) => match &s.fields() {
StructFields::Unit => "struct {name}".to_string(),
StructFields::Named(_) => todo!(),
StructFields::Unnamed(_) => todo!(),
// fields => {
// let generics = (!s.generics().is_empty())
// .then(|| format!("<{}>", s.generics().join(", ")))
// .unwrap_or_default();

// let fields = fields
// .iter()
// .map(|f| {
// let name = &f.name;
// let typ = datatype(&f.ty)?;
// Ok(format!("\t{name}: {typ}"))
// })
// .collect::<Result<Vec<_>, String>>()?
// .join(", ");
// let fields = fields
// .iter()
// .map(|f| {
// let name = &f.name;
// let typ = datatype(&f.ty)?;
// Ok(format!("\t{name}: {typ}"))
// })
// .collect::<Result<Vec<_>, String>>()?
// .join(", ");

// let tag = s
// .tag()
// .clone()
// .map(|t| format!("{t}: String"))
// .unwrap_or_default();
// let tag = s
// .tag()
// .clone()
// .map(|t| format!("{t}: String"))
// .unwrap_or_default();

// format!("struct {}{generics} {{ {fields}{tag} }}\n", s.name())
// }
// format!("struct {}{generics} {{ {fields}{tag} }}\n", s.name())
// }

todo!();
}
},
DataType::Enum(_) => todo!(),
DataType::Reference(reference) => match &reference.generics()[..] {
[] => reference.name().to_string(),
Expand Down
25 changes: 17 additions & 8 deletions specta-typescript/src/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl Default for Typescript {
Self {
header: Cow::Borrowed(""),
framework_header: Cow::Borrowed(
"// This file has been generated by Specta. DO NOT EDIT.\n",
"// This file has been generated by Specta. DO NOT EDIT.",
),
bigint: Default::default(),
comment_exporter: Some(comments::js_doc),
Expand All @@ -83,11 +83,9 @@ impl Typescript {
/// Override the header for the exported file.
/// You should prefer `Self::header` instead unless your a framework.
#[doc(hidden)] // Although this is hidden it's still public API.
pub fn framework_header(self, header: impl Into<Cow<'static, str>>) -> Self {
Self {
header: header.into(),
..Default::default()
}
pub fn framework_header(mut self, header: impl Into<Cow<'static, str>>) -> Self {
self.framework_header = header.into();
self
}

/// Configure a header for the file.
Expand Down Expand Up @@ -132,11 +130,11 @@ impl Typescript {
/// TODO
pub fn export(&self, types: &TypeCollection) -> Result<String, ExportError> {
let mut out = self.header.to_string();
out += &self.framework_header;
if !out.is_empty() {
out.push('\n');
}
out.push('\n');
out += &self.framework_header;
out.push_str("\n\n");

if let Some((ty_name, l0, l1)) = detect_duplicate_type_names(&types).into_iter().next() {
return Err(ExportError::DuplicateTypeName(ty_name, l0, l1));
Expand All @@ -159,6 +157,9 @@ impl Typescript {
types: &TypeCollection,
) -> Result<(), ExportError> {
let path = path.as_ref();
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)?;
}
std::fs::write(
&path,
self.export(types).map(|s| format!("{}{s}", self.header))?,
Expand All @@ -168,4 +169,12 @@ impl Typescript {
}
Ok(())
}

/// TODO
pub fn format(&self, path: impl AsRef<Path>) -> Result<(), ExportError> {
if let Some(formatter) = self.formatter {
formatter(path.as_ref())?;
}
Ok(())
}
}

0 comments on commit bf3a093

Please sign in to comment.