Skip to content

Commit

Permalink
Cleanup LanguageExt
Browse files Browse the repository at this point in the history
  • Loading branch information
oscartbeaumont committed Aug 1, 2024
1 parent 9e91bf7 commit 8cf9659
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 162 deletions.
175 changes: 91 additions & 84 deletions src/lang/js.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use heck::ToLowerCamelCase;
use specta::datatype::FunctionResultVariant;
use specta_typescript::js_doc;
use specta_typescript::{js_doc, ExportError, Typescript};

use crate::{ExportContext, LanguageExt};

Expand All @@ -9,97 +9,104 @@ use super::js_ts;
const GLOBALS: &str = include_str!("./globals.js");

impl LanguageExt for specta_jsdoc::JSDoc {
fn render_commands(&self, cfg: &ExportContext) -> Result<String, Self::Error> {
let commands = cfg
.commands
fn render(&self, cfg: &ExportContext) -> Result<String, Self::Error> {
let dependant_types = cfg
.type_map
.iter()
.map(|function| {
let jsdoc = {
let ret_type = js_ts::handle_result(function, &cfg.type_map, &self.0)?;

let mut builder = js_doc::Builder::default();

if let Some(d) = function.deprecated() {
builder.push_deprecated(d);
}

if !function.docs().is_empty() {
builder.extend(function.docs().split("\n"));
}

builder.extend(function.args().flat_map(|(name, typ)| {
specta_typescript::datatype(
&self.0,
&FunctionResultVariant::Value(typ.clone()),
&cfg.type_map,
)
.map(|typ| {
let name = name.to_lower_camel_case();

format!("@param {{ {typ} }} {name}")
})
}));
builder.push(&format!("@returns {{ Promise<{ret_type}> }}"));

builder.build()
};

Ok(js_ts::function(
&jsdoc,
&function.name().to_lower_camel_case(),
// TODO: Don't `collect` the whole thing
&js_ts::arg_names(&function.args().cloned().collect::<Vec<_>>()),
None,
&js_ts::command_body(&cfg.plugin_name, function, false),
))
})
.collect::<Result<Vec<_>, Self::Error>>()?
.join(",\n");

Ok(format!(
r#"export const commands = {{
{commands}
}}"#
))
}
.map(|(_sid, ndt)| js_doc::typedef_named_datatype(&self.0, ndt, &cfg.type_map))
.collect::<Result<Vec<_>, _>>()
.map(|v| v.join("\n"))?;

fn render_events(&self, cfg: &ExportContext) -> Result<String, Self::Error> {
if cfg.events.is_empty() {
return Ok(Default::default());
}
js_ts::render_all_parts::<Self>(
cfg,
&dependant_types,
GLOBALS,
&self.0.header,
render_commands(&self.0, cfg)?,
render_events(&self.0, cfg)?,
)
}
}

let (events_types, events_map) =
js_ts::events_data(&cfg.events, &self.0, &cfg.plugin_name, &cfg.type_map)?;
fn render_commands(ts: &Typescript, cfg: &ExportContext) -> Result<String, ExportError> {
let commands = cfg
.commands
.iter()
.map(|function| {
let jsdoc = {
let ret_type = js_ts::handle_result(function, &cfg.type_map, ts)?;

let mut builder = js_doc::Builder::default();

if let Some(d) = function.deprecated() {
builder.push_deprecated(d);
}

if !function.docs().is_empty() {
builder.extend(function.docs().split("\n"));
}

builder.extend(function.args().flat_map(|(name, typ)| {
specta_typescript::datatype(
ts,
&FunctionResultVariant::Value(typ.clone()),
&cfg.type_map,
)
.map(|typ| {
let name = name.to_lower_camel_case();

format!("@param {{ {typ} }} {name}")
})
}));
builder.push(&format!("@returns {{ Promise<{ret_type}> }}"));

builder.build()
};

Ok(js_ts::function(
&jsdoc,
&function.name().to_lower_camel_case(),
// TODO: Don't `collect` the whole thing
&js_ts::arg_names(&function.args().cloned().collect::<Vec<_>>()),
None,
&js_ts::command_body(&cfg.plugin_name, function, false),
))
})
.collect::<Result<Vec<_>, _>>()?
.join(",\n");

Ok(format!(
r#"export const commands = {{
{commands}
}}"#
))
}

let events = {
let mut builder = js_doc::Builder::default();
fn render_events(ts: &Typescript, cfg: &ExportContext) -> Result<String, ExportError> {
if cfg.events.is_empty() {
return Ok(Default::default());
}

builder.push("@type {typeof __makeEvents__<{");
builder.extend(events_types);
builder.push("}>}");
let (events_types, events_map) =
js_ts::events_data(&cfg.events, ts, &cfg.plugin_name, &cfg.type_map)?;

builder.build()
};
let events = {
let mut builder = js_doc::Builder::default();

Ok(format! {
r#"
{events}
const __typedMakeEvents__ = __makeEvents__;
builder.push("@type {typeof __makeEvents__<{");
builder.extend(events_types);
builder.push("}>}");

export const events = __typedMakeEvents__({{
{events_map}
}})"#
})
}
builder.build()
};

fn render(&self, cfg: &ExportContext) -> Result<String, Self::Error> {
let dependant_types = cfg
.type_map
.iter()
.map(|(_sid, ndt)| js_doc::typedef_named_datatype(&self.0, ndt, &cfg.type_map))
.collect::<Result<Vec<_>, _>>()
.map(|v| v.join("\n"))?;
Ok(format! {
r#"
{events}
const __typedMakeEvents__ = __makeEvents__;
js_ts::render_all_parts::<Self>(self, cfg, &dependant_types, GLOBALS, &self.0.header)
}
export const events = __typedMakeEvents__({{
{events_map}
}})"#
})
}
7 changes: 2 additions & 5 deletions src/lang/js_ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,13 @@ use crate::{apply_as_prefix, ExportContext, ItemType, LanguageExt};
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 fn render_all_parts<L: LanguageExt + 'static>(
language: &L,
cfg: &ExportContext,
dependant_types: &str,
globals: &str,
header: &str,
commands: String,
events: String,
) -> Result<String, L::Error> {
let commands = language.render_commands(&cfg)?;
let events = language.render_events(&cfg)?;

// TODO: Bring this back
let constants = cfg
.constants
.iter()
Expand Down
133 changes: 70 additions & 63 deletions src/lang/ts.rs
Original file line number Diff line number Diff line change
@@ -1,91 +1,98 @@
use crate::{lang::js_ts, ExportContext, LanguageExt};
use heck::ToLowerCamelCase;
use specta::datatype::FunctionResultVariant;
use specta_typescript as ts;
use specta_typescript::{self as ts, Typescript};
use specta_typescript::{js_doc, ExportError};

const GLOBALS: &str = include_str!("./globals.ts");

impl LanguageExt for specta_typescript::Typescript {
fn render_commands(&self, cfg: &ExportContext) -> Result<String, ExportError> {
let commands = cfg
.commands
fn render(&self, cfg: &ExportContext) -> Result<String, ExportError> {
let dependant_types = cfg
.type_map
.iter()
.map(|function| {
let arg_defs = function
.args()
.map(|(name, typ)| {
ts::datatype(
self,
&FunctionResultVariant::Value(typ.clone()),
&cfg.type_map,
)
.map(|ty| format!("{}: {}", name.to_lower_camel_case(), ty))
})
.collect::<Result<Vec<_>, _>>()?;
.map(|(_sid, ndt)| ts::export_named_datatype(&self, ndt, &cfg.type_map))
.collect::<Result<Vec<_>, _>>()
.map(|v| v.join("\n"))?;

js_ts::render_all_parts::<Self>(
cfg,
&dependant_types,
GLOBALS,
&self.header,
render_commands(self, cfg)?,
render_events(self, cfg)?,
)
}
}

let ret_type = js_ts::handle_result(function, &cfg.type_map, self)?;
fn render_commands(ts: &Typescript, cfg: &ExportContext) -> Result<String, ExportError> {
let commands = cfg
.commands
.iter()
.map(|function| {
let arg_defs = function
.args()
.map(|(name, typ)| {
ts::datatype(
ts,
&FunctionResultVariant::Value(typ.clone()),
&cfg.type_map,
)
.map(|ty| format!("{}: {}", name.to_lower_camel_case(), ty))
})
.collect::<Result<Vec<_>, _>>()?;

let docs = {
let mut builder = js_doc::Builder::default();
let ret_type = js_ts::handle_result(function, &cfg.type_map, ts)?;

if let Some(d) = &function.deprecated() {
builder.push_deprecated(d);
}
let docs = {
let mut builder = js_doc::Builder::default();

if !function.docs().is_empty() {
builder.extend(function.docs().split("\n"));
}
if let Some(d) = &function.deprecated() {
builder.push_deprecated(d);
}

builder.build()
};
Ok(js_ts::function(
&docs,
&function.name().to_lower_camel_case(),
&arg_defs,
Some(&ret_type),
&js_ts::command_body(&cfg.plugin_name, function, true),
))
})
.collect::<Result<Vec<_>, ExportError>>()?
.join(",\n");
if !function.docs().is_empty() {
builder.extend(function.docs().split("\n"));
}

builder.build()
};
Ok(js_ts::function(
&docs,
&function.name().to_lower_camel_case(),
&arg_defs,
Some(&ret_type),
&js_ts::command_body(&cfg.plugin_name, function, true),
))
})
.collect::<Result<Vec<_>, ExportError>>()?
.join(",\n");

Ok(format! {
r#"
Ok(format! {
r#"
export const commands = {{
{commands}
}}"#
})
}
})
}

fn render_events(&self, cfg: &ExportContext) -> Result<String, ExportError> {
if cfg.events.is_empty() {
return Ok(Default::default());
}
fn render_events(ts: &Typescript, cfg: &ExportContext) -> Result<String, ExportError> {
if cfg.events.is_empty() {
return Ok(Default::default());
}

let (events_types, events_map) =
js_ts::events_data(&cfg.events, self, &cfg.plugin_name, &cfg.type_map)?;
let (events_types, events_map) =
js_ts::events_data(&cfg.events, ts, &cfg.plugin_name, &cfg.type_map)?;

let events_types = events_types.join(",\n");
let events_types = events_types.join(",\n");

Ok(format! {
r#"
Ok(format! {
r#"
export const events = __makeEvents__<{{
{events_types}
}}>({{
{events_map}
}})"#
})
}

fn render(&self, cfg: &ExportContext) -> Result<String, ExportError> {
let dependant_types = cfg
.type_map
.iter()
.map(|(_sid, ndt)| ts::export_named_datatype(&self, ndt, &cfg.type_map))
.collect::<Result<Vec<_>, _>>()
.map(|v| v.join("\n"))?;

js_ts::render_all_parts::<Self>(self, cfg, &dependant_types, GLOBALS, &self.header)
}
})
}
10 changes: 0 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,20 +192,10 @@ pub struct ExportContext {
/// - [`specta_typescript::Typescript`]
/// - [`specta_jsdoc::JSDoc`]
pub trait LanguageExt: Language {
fn render_commands(&self, cfg: &ExportContext) -> Result<String, Self::Error>;
fn render_events(&self, cfg: &ExportContext) -> Result<String, Self::Error>;
fn render(&self, cfg: &ExportContext) -> Result<String, Self::Error>;
}

impl<L: LanguageExt> LanguageExt for &L {
fn render_commands(&self, cfg: &ExportContext) -> Result<String, Self::Error> {
(*self).render_commands(cfg)
}

fn render_events(&self, cfg: &ExportContext) -> Result<String, Self::Error> {
(*self).render_events(cfg)
}

fn render(&self, cfg: &ExportContext) -> Result<String, Self::Error> {
(*self).render(cfg)
}
Expand Down

0 comments on commit 8cf9659

Please sign in to comment.