Skip to content

Commit

Permalink
Combine #195 with e2e
Browse files Browse the repository at this point in the history
  • Loading branch information
escritorio-gustavo committed Feb 1, 2024
1 parent fdeb8c8 commit 7e3f169
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 8 deletions.
2 changes: 2 additions & 0 deletions e2e/dependencies/consumer/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[env]
TS_RS_EXPORT_DIR = { value = "./bindings/", relative = true }
8 changes: 7 additions & 1 deletion e2e/dependencies/dependency1/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
use ts_rs::TS;

#[derive(TS)]
#[ts(export)]
pub struct LibraryType {
pub a: i32
}
}

#[test]
fn env_set() {
assert_ne!(env!("TS_RS_EXPORT_DIR"), "");
}
2 changes: 2 additions & 0 deletions e2e/workspace/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[env]
TS_RS_EXPORT_DIR = { value = "./bindings/", relative = true }
3 changes: 2 additions & 1 deletion e2e/workspace/crate1/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use ts_rs::TS;

#[derive(TS)]
#[ts(export)]
pub struct Crate1 {
pub x: i32
}
}
1 change: 1 addition & 0 deletions e2e/workspace/crate2/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use ts_rs::TS;

#[derive(TS)]
#[ts(export)]
pub struct Crate2 {
pub x: i32
}
7 changes: 7 additions & 0 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,18 @@ impl DerivedTS {
}

fn into_impl(self, rust_ty: Ident, generics: Generics) -> TokenStream {
let mut get_export_to = quote! {};
let export_to = match &self.export_to {
Some(dirname) if dirname.ends_with('/') => {
format!("{}{}.ts", dirname, self.name)
}
Some(filename) => filename.clone(),
None => {
get_export_to = quote! {
fn get_export_to() -> Option<String> {
ts_rs::__private::get_export_to_path::<Self>()
}
};
format!("bindings/{}.ts", self.name)
}
};
Expand Down Expand Up @@ -84,6 +90,7 @@ impl DerivedTS {
quote! {
#impl_start {
const EXPORT_TO: Option<&'static str> = Some(#export_to);
#get_export_to

fn decl() -> String {
#decl
Expand Down
31 changes: 28 additions & 3 deletions ts-rs/src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{
collections::BTreeMap,
fmt::Write,
path::{Component, Path, PathBuf},
sync::OnceLock,
};

use thiserror::Error;
Expand Down Expand Up @@ -59,6 +60,29 @@ pub(crate) fn export_type_to<T: TS + ?Sized + 'static, P: AsRef<Path>>(
Ok(())
}


#[doc(hidden)]
pub mod __private {
use super::*;

const EXPORT_DIR_ENV_VAR: &str = "TS_RS_EXPORT_DIR";
fn provided_default_dir() -> &'static Option<String> {
static EXPORT_TO: OnceLock<Option<String>> = OnceLock::new();
EXPORT_TO.get_or_init(|| std::env::var(EXPORT_DIR_ENV_VAR).ok())
}

/// Returns the path to where `T` should be exported using the `TS_RS_EXPORT_DIR` environment variable.
///
/// This should only be used by the TS derive macro; the `get_export_to` trait method should not
/// be overridden if the `#[ts(export_to = ..)]` attribute exists.
pub fn get_export_to_path<T: TS + ?Sized>() -> Option<String> {
provided_default_dir().as_ref().map_or_else(
|| T::EXPORT_TO.map(ToString::to_string),
|path| Some(format!("{path}/{}.ts", T::name())),
)
}
}

/// Returns the generated defintion for `T`.
pub(crate) fn export_type_to_string<T: TS + ?Sized + 'static>() -> Result<String, ExportError> {
let mut buffer = String::with_capacity(1024);
Expand All @@ -72,7 +96,7 @@ pub(crate) fn export_type_to_string<T: TS + ?Sized + 'static>() -> Result<String
fn output_path<T: TS + ?Sized>() -> Result<PathBuf, ExportError> {
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").map_err(|_| ManifestDirNotSet)?;
let manifest_dir = Path::new(&manifest_dir);
let path = PathBuf::from(T::EXPORT_TO.ok_or(CannotBeExported)?);
let path = PathBuf::from(T::get_export_to().ok_or(CannotBeExported)?);
Ok(manifest_dir.join(path))
}

Expand All @@ -84,7 +108,8 @@ fn generate_decl<T: TS + ?Sized>(out: &mut String) {

/// Push an import statement for all dependencies of `T`
fn generate_imports<T: TS + ?Sized + 'static>(out: &mut String) -> Result<(), ExportError> {
let path = Path::new(T::EXPORT_TO.ok_or(ExportError::CannotBeExported)?);
let export_to = T::get_export_to().ok_or(CannotBeExported)?;
let path = Path::new(&export_to);

let deps = T::dependencies();
let deduplicated_deps = deps
Expand All @@ -94,7 +119,7 @@ fn generate_imports<T: TS + ?Sized + 'static>(out: &mut String) -> Result<(), Ex
.collect::<BTreeMap<_, _>>();

for (_, dep) in deduplicated_deps {
let rel_path = import_path(path, Path::new(dep.exported_to));
let rel_path = import_path(path, Path::new(&dep.exported_to));
writeln!(
out,
"import type {{ {} }} from {:?};",
Expand Down
10 changes: 7 additions & 3 deletions ts-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ use std::{

pub use ts_rs_macros::TS;

pub use crate::export::ExportError;
pub use crate::export::{ExportError, __private};

#[cfg(feature = "chrono-impl")]
mod chrono;
Expand Down Expand Up @@ -263,6 +263,10 @@ mod export;
pub trait TS {
const EXPORT_TO: Option<&'static str> = None;

fn get_export_to() -> Option<String> {
Self::EXPORT_TO.map(ToString::to_string)
}

/// Declaration of this type, e.g. `interface User { user_id: number, ... }`.
/// This function will panic if the type has no declaration.
fn decl() -> String {
Expand Down Expand Up @@ -342,15 +346,15 @@ pub struct Dependency {
pub ts_name: String,
/// Path to where the type would be exported. By default a filename is derived from the types
/// name, which can be customized with `#[ts(export_to = "..")]`.
pub exported_to: &'static str,
pub exported_to: String,
}

impl Dependency {
/// Constructs a [`Dependency`] from the given type `T`.
/// If `T` is not exportable (meaning `T::EXPORT_TO` is `None`), this function will return
/// `None`
pub fn from_ty<T: TS + 'static + ?Sized>() -> Option<Self> {
let exported_to = T::EXPORT_TO?;
let exported_to = T::get_export_to()?;
Some(Dependency {
type_id: TypeId::of::<T>(),
ts_name: T::name(),
Expand Down

0 comments on commit 7e3f169

Please sign in to comment.