From 3087ba33d9083a48e6821e25a601f50c46be3bf3 Mon Sep 17 00:00:00 2001 From: Oscar Beaumont Date: Thu, 1 Aug 2024 11:12:35 +0800 Subject: [PATCH] Drop `ExportConfig` --- src/builder.rs | 16 +++------- src/js_ts.rs | 81 ++++++++++++++++++++---------------------------- src/lib.rs | 84 +++++++++++++++++++++++++++----------------------- src/ts.rs | 43 ++++++++++---------------- 4 files changed, 101 insertions(+), 123 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 6e97cfa..4e25ade 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -135,32 +135,26 @@ impl Builder { .collect::, _>>() .map(|v| v.join("\n"))?; - let cfg = crate::ExportConfig { - plugin_name: self.plugin_name.map(PluginName), - path: language.path.clone(), - header: language.header.clone(), - inner: language.clone(), - }; - let rendered = crate::js_ts::render_all_parts::( &commands, &self.events.1, &self.types, &Default::default(), // TODO: fix statics - &cfg, + &language, + &self.plugin_name, &dependant_types, crate::ts::GLOBALS, )?; - write!(file, "{}", format!("{}\n{rendered}", cfg.inner.header))?; + write!(file, "{}", format!("{}\n{rendered}", language.header))?; - cfg.inner.run_format(path.clone()).ok(); + language.run_format(path.clone()).ok(); } Ok(()) } pub fn export_js_doc(&self, language: Typescript) { - // TODO + todo!(); } } diff --git a/src/js_ts.rs b/src/js_ts.rs index b4d1b7f..7126dab 100644 --- a/src/js_ts.rs +++ b/src/js_ts.rs @@ -7,30 +7,29 @@ use specta::{ datatype::{DataType, FunctionResultVariant}, TypeMap, }; -use specta_typescript::ExportError; use specta_typescript::{self as ts}; +use specta_typescript::{ExportError, Typescript}; -use crate::{EventDataType, ExportLanguage, ItemType, StaticCollection}; +use crate::{apply_as_prefix, EventDataType, ItemType, LanguageExt, StaticCollection}; -pub 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 DO_NOT_EDIT: &str = "// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually."; +// TODO: Remove this const CRINGE_ESLINT_DISABLE: &str = "/* eslint-disable */ "; -pub type ExportConfig = crate::ExportConfig; - -pub fn render_all_parts>( +// TODO: Can we avoid hardcoding error type??? +pub fn render_all_parts>( commands: &[datatype::Function], events: &[EventDataType], type_map: &TypeMap, statics: &StaticCollection, - // plugin_name: &str, - // cfg: &Typescript, - cfg: &ExportConfig, + cfg: &Typescript, + plugin_name: &Option<&'static str>, dependant_types: &str, globals: &str, ) -> Result { - let commands = T::render_commands(commands, type_map, cfg)?; - let events = T::render_events(events, type_map, cfg)?; + let commands = cfg.render_commands(commands, type_map, plugin_name)?; + let events = cfg.render_events(events, type_map, plugin_name)?; let statics = statics .statics @@ -148,37 +147,31 @@ fn tauri_invoke(name: &str, arg_usages: Option) -> String { pub fn handle_result( function: &datatype::Function, type_map: &TypeMap, - cfg: &ExportConfig, + cfg: &Typescript, ) -> Result { Ok(match &function.result() { Some(FunctionResultVariant::Result(t, e)) => { format!( "Result<{}, {}>", - ts::datatype( - &cfg.inner, - &FunctionResultVariant::Value(t.clone()), - type_map - )?, - ts::datatype( - &cfg.inner, - &FunctionResultVariant::Value(e.clone()), - type_map - )? + ts::datatype(cfg, &FunctionResultVariant::Value(t.clone()), type_map)?, + ts::datatype(cfg, &FunctionResultVariant::Value(e.clone()), type_map)? ) } - Some(FunctionResultVariant::Value(t)) => ts::datatype( - &cfg.inner, - &FunctionResultVariant::Value(t.clone()), - type_map, - )?, + Some(FunctionResultVariant::Value(t)) => { + ts::datatype(cfg, &FunctionResultVariant::Value(t.clone()), type_map)? + } None => "void".to_string(), }) } -pub fn command_body(cfg: &ExportConfig, function: &datatype::Function, as_any: bool) -> String { - let name = cfg - .plugin_name - .map(|n| n.apply_as_prefix(&function.name(), ItemType::Command)) +pub fn command_body( + plugin_name: &Option<&'static str>, + function: &datatype::Function, + as_any: bool, +) -> String { + let name = plugin_name + .as_ref() + .map(|n| apply_as_prefix(&n, &function.name(), ItemType::Command)) .unwrap_or_else(|| function.name().to_string()); maybe_return_as_result_tuple( @@ -194,13 +187,13 @@ pub fn command_body(cfg: &ExportConfig, function: &datatype::Function, as_any: b ) } -pub fn events_map(events: &[EventDataType], cfg: &ExportConfig) -> String { +pub fn events_map(events: &[EventDataType], plugin_name: &Option<&'static str>) -> String { events .iter() .map(|event| { - let name_str = cfg - .plugin_name - .map(|n| n.apply_as_prefix(event.name, ItemType::Event)) + let name_str = plugin_name + .as_ref() + .map(|n| apply_as_prefix(n, event.name, ItemType::Event)) .unwrap_or_else(|| event.name.to_string()); let name_camel = event.name.to_lower_camel_case(); @@ -212,7 +205,7 @@ pub fn events_map(events: &[EventDataType], cfg: &ExportConfig) -> String { pub fn events_types( events: &[EventDataType], - cfg: &ExportConfig, + cfg: &Typescript, type_map: &TypeMap, ) -> Result, ExportError> { events @@ -221,7 +214,7 @@ pub fn events_types( let name_camel = event.name.to_lower_camel_case(); let typ = ts::datatype( - &cfg.inner, + cfg, &FunctionResultVariant::Value(event.typ.clone()), type_map, )?; @@ -233,20 +226,12 @@ pub fn events_types( pub fn events_data( events: &[EventDataType], - cfg: &ExportConfig, + cfg: &Typescript, + plugin_name: &Option<&'static str>, type_map: &TypeMap, ) -> Result<(Vec, String), ExportError> { Ok(( events_types(events, cfg, type_map)?, - events_map(events, cfg), + events_map(events, plugin_name), )) } - -impl From for ExportConfig { - fn from(config: specta_typescript::Typescript) -> Self { - Self { - header: CRINGE_ESLINT_DISABLE.into(), - ..Self::new(config) - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 132807d..bb25a4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -116,7 +116,7 @@ use std::{borrow::Cow, error, fmt, path::PathBuf}; -use specta::{datatype, TypeMap}; +use specta::{datatype, Language, TypeMap}; #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] @@ -127,7 +127,7 @@ mod builder; pub mod internal; mod macros; -pub use builder::Builder; // TODO: Rename +pub use builder::Builder; /// The exporter for [Javascript](https://www.javascript.com). #[cfg(feature = "javascript")] @@ -149,36 +149,32 @@ mod statics; pub use event::*; pub use statics::StaticCollection; -/// A set of functions that produce language-specific code -pub trait ExportLanguage: 'static { - type Config: Default + Clone; // TODO: Remove - type Error: fmt::Debug + error::Error + From; // TODO: Review if this `From` should be removed before stabilisation - - fn run_format(path: PathBuf, cfg: &ExportConfig); - - fn render_events( - events: &[EventDataType], +pub trait LanguageExt: Language { + fn render_commands( + &self, + commands: &[datatype::Function], type_map: &TypeMap, - cfg: &ExportConfig, + plugin_name: &Option<&'static str>, ) -> Result; - /// Renders a collection of [`FunctionDataType`] into a string. - fn render_commands( - commands: &[datatype::Function], + fn render_events( + &self, + events: &[EventDataType], type_map: &TypeMap, - cfg: &ExportConfig, + plugin_name: &Option<&'static str>, ) -> Result; - /// Renders the output of [`globals`], [`render_functions`] and all dependant types into a TypeScript string. fn render( + &self, commands: &[datatype::Function], events: &[EventDataType], type_map: &TypeMap, statics: &StaticCollection, - cfg: &ExportConfig, + plugin_name: &Option<&'static str>, ) -> Result; } +// TODO: Remove #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub(crate) struct PluginName(&'static str); @@ -205,25 +201,37 @@ impl PluginName { } } -/// The configuration for the generator -#[derive(Default, Clone)] -pub struct ExportConfig { - /// The name of the plugin to invoke. - /// - /// If there is no plugin name (i.e. this is an app), this should be `None`. - pub(crate) plugin_name: Option, - /// The specta export configuration - pub(crate) inner: TConfig, - pub(crate) path: Option, - pub(crate) header: Cow<'static, str>, +pub(crate) fn apply_as_prefix(plugin_name: &str, s: &str, item_type: ItemType) -> String { + format!( + "plugin:{}{}{}", + plugin_name, + match item_type { + ItemType::Event => ":", + ItemType::Command => "|", + }, + s, + ) } -impl ExportConfig { - /// Creates a new [`ExportConfiguration`] from a [`specta::ts::ExportConfiguration`] - pub fn new(config: TConfig) -> Self { - Self { - inner: config, - ..Default::default() - } - } -} +// // TODO: Remove +// #[derive(Default, Clone)] +// pub struct ExportConfig { +// /// The name of the plugin to invoke. +// /// +// /// If there is no plugin name (i.e. this is an app), this should be `None`. +// pub(crate) plugin_name: Option, +// /// The specta export configuration +// pub(crate) inner: TConfig, +// pub(crate) path: Option, +// pub(crate) header: Cow<'static, str>, +// } + +// impl ExportConfig { +// /// Creates a new [`ExportConfiguration`] from a [`specta::ts::ExportConfiguration`] +// pub fn new(config: TConfig) -> Self { +// Self { +// inner: config, +// ..Default::default() +// } +// } +// } diff --git a/src/ts.rs b/src/ts.rs index b1be68a..c9f588a 100644 --- a/src/ts.rs +++ b/src/ts.rs @@ -5,24 +5,16 @@ use specta::{datatype, datatype::FunctionResultVariant}; use specta_typescript as ts; use specta_typescript::{js_doc, ExportError}; -const GLOBALS: &str = include_str!("./globals.ts"); - -type Config = specta_typescript::Typescript; -pub type ExportConfig = crate::ExportConfig; - -impl ExportLanguage for specta_typescript::Typescript { - type Config = Config; - type Error = ts::ExportError; - - fn run_format(path: PathBuf, cfg: &ExportConfig) { - cfg.inner.run_format(path).ok(); - } +// TODO: Make private +pub(crate) const GLOBALS: &str = include_str!("./globals.ts"); +impl LanguageExt for specta_typescript::Typescript { /// Renders a collection of [`FunctionDataType`] into a TypeScript string. fn render_commands( + &self, commands: &[datatype::Function], type_map: &TypeMap, - cfg: &ExportConfig, + plugin_name: &Option<&'static str>, ) -> Result { let commands = commands .iter() @@ -30,16 +22,12 @@ impl ExportLanguage for specta_typescript::Typescript { let arg_defs = function .args() .map(|(name, typ)| { - ts::datatype( - &cfg.inner, - &FunctionResultVariant::Value(typ.clone()), - type_map, - ) - .map(|ty| format!("{}: {}", name.to_lower_camel_case(), ty)) + ts::datatype(self, &FunctionResultVariant::Value(typ.clone()), type_map) + .map(|ty| format!("{}: {}", name.to_lower_camel_case(), ty)) }) .collect::, _>>()?; - let ret_type = js_ts::handle_result(function, type_map, cfg)?; + let ret_type = js_ts::handle_result(function, type_map, self)?; let docs = { let mut builder = js_doc::Builder::default(); @@ -59,7 +47,7 @@ impl ExportLanguage for specta_typescript::Typescript { &function.name().to_lower_camel_case(), &arg_defs, Some(&ret_type), - &js_ts::command_body(cfg, function, true), + &js_ts::command_body(plugin_name, function, true), )) }) .collect::, ExportError>>()? @@ -74,15 +62,16 @@ impl ExportLanguage for specta_typescript::Typescript { } fn render_events( + &self, events: &[EventDataType], type_map: &TypeMap, - cfg: &ExportConfig, + plugin_name: &Option<&'static str>, ) -> Result { if events.is_empty() { return Ok(Default::default()); } - let (events_types, events_map) = js_ts::events_data(events, cfg, type_map)?; + let (events_types, events_map) = js_ts::events_data(events, self, plugin_name, type_map)?; let events_types = events_types.join(",\n"); @@ -97,15 +86,16 @@ impl ExportLanguage for specta_typescript::Typescript { } fn render( + &self, commands: &[datatype::Function], events: &[EventDataType], type_map: &TypeMap, statics: &StaticCollection, - cfg: &ExportConfig, + plugin_name: &Option<&'static str>, ) -> Result { let dependant_types = type_map .iter() - .map(|(_sid, ndt)| ts::export_named_datatype(&cfg.inner, ndt, type_map)) + .map(|(_sid, ndt)| ts::export_named_datatype(&self, ndt, type_map)) .collect::, _>>() .map(|v| v.join("\n"))?; @@ -114,7 +104,8 @@ impl ExportLanguage for specta_typescript::Typescript { events, type_map, statics, - cfg, + self, + plugin_name, &dependant_types, GLOBALS, )