Skip to content

Commit

Permalink
move specta_util::export to specta::export
Browse files Browse the repository at this point in the history
  • Loading branch information
Oscar Beaumont authored and Oscar Beaumont committed Dec 4, 2024
1 parent 1220b8f commit ed420ac
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 38 deletions.
3 changes: 1 addition & 2 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ edition = "2021"
publish = false

[dependencies]
specta = { path = "../specta", features = ["derive"] }
specta = { path = "../specta", features = ["derive", "export"] }
specta-typescript = { path = "../specta-typescript" }
specta-util = { path = "../specta-util", features = ["export"] }

[lints]
workspace = true
6 changes: 3 additions & 3 deletions examples/examples/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ pub struct TypeTwo {

fn main() {
// Export as string
let string = specta_util::export().export(Typescript::default()).unwrap();
let string = specta::export().export(Typescript::default()).unwrap();
println!("{string}");

// Export to file
specta_util::export()
specta::export()
.export_to(Typescript::default(), "./bindings.ts")
.unwrap();

// Override the export configuration.
specta_util::export()
specta::export()
.export_to(
Typescript::default()
// Be aware this won't be typesafe unless your using a ser/deserializer that converts BigInt types to a number.
Expand Down
5 changes: 2 additions & 3 deletions specta-macros/src/type/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ pub fn derive(input: proc_macro::TokenStream) -> syn::Result<proc_macro::TokenSt
.unwrap_or_else(|| ident.to_token_stream());

let crate_ref: TokenStream = container_attrs.crate_name.clone().unwrap_or(quote!(specta));
let internal_crate_ref: TokenStream = quote!(specta_util); // TODO: This should be overridable by attribute but it's not. // TODO: container_attrs.crate_name.clone().unwrap_or(

let name = container_attrs.rename.clone().unwrap_or_else(|| {
unraw_raw_ident(&format_ident!("{}", raw_ident.to_string())).to_token_stream()
Expand Down Expand Up @@ -119,9 +118,9 @@ pub fn derive(input: proc_macro::TokenStream) -> syn::Result<proc_macro::TokenSt

quote! {
#[allow(non_snake_case)]
#[#internal_crate_ref::export::internal::ctor]
#[#crate_ref::export::internal::ctor]
fn #export_fn_name() {
#internal_crate_ref::export::internal::register::<#ident<#(#generic_params),*>>();
#crate_ref::export::internal::register::<#ident<#(#generic_params),*>>();
}
}
});
Expand Down
15 changes: 3 additions & 12 deletions specta-typescript/src/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ pub enum BigIntExportBehavior {
pub struct Typescript {
/// The file's header
pub header: Cow<'static, str>,
/// Should we remove the default header?
pub remove_default_header: bool,
/// How BigInts should be exported.
pub bigint: BigIntExportBehavior,
/// How comments should be rendered.
Expand All @@ -68,7 +66,6 @@ impl Default for Typescript {
fn default() -> Self {
Self {
header: Cow::Borrowed(""),
remove_default_header: false,
bigint: Default::default(),
comment_exporter: Some(comments::js_doc),
formatter: None,
Expand All @@ -90,13 +87,6 @@ impl Typescript {
self
}

// TODO: Only keep this is TS stays responsible for exporting which it probs won't.
/// Removes the default Specta header from the output.
pub fn remove_default_header(mut self) -> Self {
self.remove_default_header = true;
self
}

/// Configure the BigInt handling behaviour
pub fn bigint(mut self, bigint: BigIntExportBehavior) -> Self {
self.bigint = bigint;
Expand Down Expand Up @@ -134,9 +124,10 @@ impl Language for Typescript {

fn export(&self, type_map: &TypeCollection) -> Result<String, Self::Error> {
let mut out = self.header.to_string();
if !self.remove_default_header {
out += "// This file has been generated by Specta. DO NOT EDIT.\n\n";
if !self.header.is_empty() {
out.push('\n');
}
out.push('\n');

if let Some((ty_name, l0, l1)) = detect_duplicate_type_names(&type_map).into_iter().next() {
return Err(ExportError::DuplicateTypeName(ty_name, l0, l1));
Expand Down
3 changes: 0 additions & 3 deletions specta-util/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ rustdoc-args = ["--cfg", "docsrs"]

[features]
default = []
## Support for collecting up a global type map
export = ["dep:ctor", "specta-macros/DO_NOT_USE_export"]

# TODO: Can we remove this?
serde = []
Expand All @@ -29,5 +27,4 @@ workspace = true
[dependencies]
specta = { version = "=2.0.0-rc.20", path = "../specta" }
specta-macros = { version = "=2.0.0-rc.17", path = "../specta-macros", default-features = false, optional = true }
ctor = { version = "0.2.8", default-features = false, optional = true }
serde = "1.0.204" # TODO: Can we remove this or at least make it optional behind the `serde` flag
10 changes: 0 additions & 10 deletions specta-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@
html_favicon_url = "https://github.com/oscartbeaumont/specta/raw/main/.github/logo-128.png"
)]

/// Provides the global type store and a method to export them to other languages.
#[cfg(feature = "export")]
#[cfg_attr(docsrs, doc(cfg(feature = "export")))]
#[doc(hidden)]
pub mod export;

#[cfg(feature = "export")]
#[cfg_attr(docsrs, doc(cfg(feature = "export")))]
pub use export::export;

#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
mod selection;
Expand Down
5 changes: 5 additions & 0 deletions specta/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ default = []
## Derive macros
derive = ["dep:specta-macros"]

## Support for collecting up a global type map
export = ["dep:ctor", "specta-macros/DO_NOT_USE_export"]

#! Features
## Support for exporting the types of Rust functions.
function = ["specta-macros?/DO_NOT_USE_function", "dep:paste"]
Expand Down Expand Up @@ -88,6 +91,8 @@ specta-macros = { version = "=2.0.0-rc.17", optional = true, path = "../specta-m
paste = { version = "1", optional = true }
thiserror = "1.0.61"

ctor = { version = "0.2.8", default-features = false, optional = true }

# TODO: To be deprecated
specta1 = { package = "specta", version = "1", optional = true, default-features = false }
serde = { version = "1.0.204", optional = true, default-features = false, features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion specta-util/src/export.rs → specta/src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{
sync::{Mutex, OnceLock, PoisonError},
};

use specta::{datatype::NamedDataType, NamedType, SpectaID, TypeCollection};
use crate::{datatype::NamedDataType, NamedType, SpectaID, TypeCollection};

// Global type store for collecting custom types to export.
static TYPES: OnceLock<Mutex<HashMap<SpectaID, fn(&mut TypeCollection) -> NamedDataType>>> =
Expand Down
9 changes: 9 additions & 0 deletions specta/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
)]

pub mod datatype;
#[cfg(feature = "export")]
#[cfg_attr(docsrs, doc(cfg(feature = "export")))]
#[doc(hidden)]
pub mod export;
#[cfg(feature = "function")]
#[cfg_attr(docsrs, doc(cfg(feature = "function")))]
pub mod function;
Expand All @@ -24,6 +28,11 @@ pub use type_collection::TypeCollection;

pub use language::Language;

#[doc(inline)]
#[cfg(feature = "export")]
#[cfg_attr(docsrs, doc(cfg(feature = "export")))]
pub use export::export;

#[doc(inline)]
#[cfg(feature = "derive")]
#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
Expand Down
35 changes: 31 additions & 4 deletions specta/src/type_collection.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
borrow::Borrow,
borrow::{Borrow, Cow},
collections::{btree_map, BTreeMap},
fmt,
path::Path,
Expand All @@ -11,12 +11,14 @@ use crate::{datatype::NamedDataType, Language, NamedType, SpectaID};
///
/// While exporting a type will add all of the types it depends on to the collection.
/// You can also construct your own collection to easily export a set of types together.
#[derive(Default, Clone, PartialEq)]
#[derive(Clone, PartialEq)]
pub struct TypeCollection {
// `None` indicates that the entry is a placeholder. It was reference and we are currently working out it's definition.
pub(crate) map: BTreeMap<SpectaID, Option<NamedDataType>>,
// A stack of types that are currently being flattened. This is used to detect cycles.
pub(crate) flatten_stack: Vec<SpectaID>,
// A header for the exported file that can be overriden by a framework built off of `specta`.
pub(crate) header: Cow<'static, str>,
}

impl fmt::Debug for TypeCollection {
Expand All @@ -25,7 +27,27 @@ impl fmt::Debug for TypeCollection {
}
}

impl Default for TypeCollection {
fn default() -> Self {
Self {
map: BTreeMap::new(),
flatten_stack: Vec::new(),
header: Cow::Borrowed("// This file has been generated by Specta. DO NOT EDIT.\n"),
}
}
}

impl TypeCollection {
/// Override the header for the exported file.
/// You should prefer setting the header using the [`Language`] instead unless your a framework.
#[doc(hidden)] // Although this is hidden it's still public API.
pub fn with_header(self, header: impl Into<Cow<'static, str>>) -> Self {
Self {
header: header.into(),
..Default::default()
}
}

/// Register a type with the collection.
pub fn register<T: NamedType>(&mut self) -> &mut Self {
let def = T::definition_named_data_type(self);
Expand Down Expand Up @@ -54,7 +76,7 @@ impl TypeCollection {

/// TODO
pub fn export<L: Language>(&self, language: L) -> Result<String, L::Error> {
language.export(self)
language.export(self).map(|s| format!("{}{s}", self.header))
}

/// TODO
Expand All @@ -64,7 +86,12 @@ impl TypeCollection {
path: impl AsRef<Path>,
) -> Result<(), L::Error> {
let path = path.as_ref();
std::fs::write(&path, language.export(self)?)?;
std::fs::write(
&path,
language
.export(self)
.map(|s| format!("{}{s}", self.header))?,
)?;
language.format(path)?;
Ok(())
}
Expand Down

0 comments on commit ed420ac

Please sign in to comment.