#![forbid(unsafe_code)]
#![warn(clippy::all, clippy::unwrap_used, clippy::panic, missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]
use std::{
borrow::Cow,
fs::{self, File},
io::Write,
marker::PhantomData,
path::{Path, PathBuf},
};
use specta::{
functions::FunctionDataType,
ts::{ExportConfiguration, TsExportError},
ExportError, TypeDefs,
};
#[cfg(feature = "javascript")]
#[cfg_attr(docsrs, doc(cfg(feature = "javascript")))]
pub mod js;
#[cfg(feature = "typescript")]
#[cfg_attr(docsrs, doc(cfg(feature = "typescript")))]
pub mod ts;
#[macro_export]
#[deprecated(
note = "Please use `specta::collect_types` instead! This alias will be removed in a future release."
)]
macro_rules! collate_types {
(type_map: $type_map:ident, $($command:path),*) => {{
specta::functions::collect_types!(type_map: $type_map, $($command),*)
}};
($($command:path),*) => {{
let mut type_map = specta::TypeDefs::default();
specta::functions::collect_types!(type_map: type_map, $($command),*)
}};
}
pub(crate) const DO_NOT_EDIT: &str = "// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually.";
pub(crate) const CRINGE_ESLINT_DISABLE: &str = "/* eslint-disable */
";
pub trait ExportLanguage {
fn globals() -> String;
fn render_functions(
function_types: Vec<FunctionDataType>,
cfg: &specta::ts::ExportConfiguration,
) -> Result<String, TsExportError>;
fn render(
function_types: Vec<FunctionDataType>,
type_map: TypeDefs,
cfg: &specta::ts::ExportConfiguration,
) -> Result<String, TsExportError>;
}
pub struct Exporter<TLang: ExportLanguage> {
macro_data: Result<(Vec<FunctionDataType>, TypeDefs), ExportError>,
export_path: PathBuf,
cfg: Option<ExportConfiguration>,
header: Cow<'static, str>,
lang: PhantomData<TLang>,
}
impl<TLang: ExportLanguage> Exporter<TLang> {
pub fn new(
macro_data: Result<(Vec<FunctionDataType>, TypeDefs), ExportError>,
export_path: impl AsRef<Path>,
) -> Self {
Self {
macro_data,
export_path: export_path.as_ref().into(),
cfg: None,
header: CRINGE_ESLINT_DISABLE.into(), lang: Default::default(),
}
}
pub fn with_cfg(mut self, cfg: ExportConfiguration) -> Self {
self.cfg = Some(cfg);
self
}
pub fn with_header(mut self, header: &'static str) -> Self {
self.header = header.into();
self
}
pub fn export(self) -> Result<(), TsExportError> {
let Self {
macro_data,
export_path,
cfg,
header,
..
} = self;
let (function_types, type_map) = macro_data?;
if let Some(export_dir) = export_path.parent() {
fs::create_dir_all(export_dir)?;
}
let mut file = File::create(export_path)?;
write!(
file,
"{}{}",
header,
TLang::render(function_types, type_map, &cfg.unwrap_or_default())?
)?;
Ok(())
}
}