1use super::*;
2
3#[derive(Default)]
4pub struct TsScript {
5 comment: Option<String>,
6 exclusive: Vec<String>,
7 exclude: Vec<String>,
8}
9
10impl TsScript {
11 pub fn new() -> Self {
12 Self::default()
13 }
14
15 pub fn with_comment<T: Into<String>>(mut self, comment: T) -> Self {
17 self.comment.replace(comment.into());
18 self
19 }
20
21 pub fn with_exclusive<T: Into<String>>(mut self, exclusive: Vec<T>) -> Self {
23 self.exclusive = exclusive.into_iter().map(|x| x.into()).collect::<Vec<_>>();
24 self
25 }
26
27 pub fn with_exclude<T: Into<String>>(mut self, exclude: Vec<T>) -> Self {
29 self.exclude.extend(exclude.into_iter().map(|x| x.into()));
30 self
31 }
32
33 pub fn build_script(&self) -> String {
35 build_ts_script_with(
36 self.comment.as_ref(),
37 self.exclusive.as_slice(),
38 self.exclude.as_slice(),
39 )
40 }
41
42 pub fn export_script(&self, path: impl AsRef<std::path::Path>) {
44 let script = self.build_script();
45
46 let path = path.as_ref();
47 if let Some(parent) = path.parent() {
48 std::fs::create_dir_all(parent).expect("Failed to create parent directories");
49 }
50 std::fs::write(path, script).expect("Failed to write Tsain TypeScript file");
51 println!(
52 "cargo:warning=Exported Tsain TypeScript definitions to {}",
53 path.display()
54 );
55 }
56
57 pub fn export(path: impl AsRef<std::path::Path>) {
59 Self::new().export_script(path);
60 }
61}
62
63fn build_ts_script_with(
64 comment: Option<&String>,
65 exclusive: &[String],
66 exclude: &[String],
67) -> String {
68 #[cfg(not(target_arch = "wasm32"))]
69 {
70 let mut script = include_str!("../script/head.txt").to_owned();
71 script.push_str("\n");
72
73 if let Some(comment) = comment {
75 script.push_str(comment);
76 script.push('\n');
77 }
78
79 script.push_str("\n\n");
80
81 for def in inventory::iter::<TsainPatternDefinition>() {
83 let pattern = (def.__pattern_fn)();
84 let exclude = (!exclusive.is_empty()
85 && !exclusive
86 .iter()
87 .find(|x| x.eq(&pattern.rs_name()))
88 .is_some())
89 || exclude.iter().find(|x| x.eq(&pattern.rs_name())).is_some();
90 if exclude {
91 continue;
92 }
93 script.push_str(&pattern.format_type_script());
94 script.push('\n');
95 }
96
97 for def in inventory::iter::<TsainAliasDefinition>() {
99 let script_ = def.__script;
100 script.push_str(script_);
101 script.push('\n');
102 }
103
104 return script;
105 }
106
107 #[allow(unreachable_code)]
108 return String::from("CAN NOT BUILD SCRIPT IN WASM TARGET");
109}
110
111#[cfg(not(target_arch = "wasm32"))]
114pub struct TsainPatternDefinition {
115 pub __pattern_fn: fn() -> TsainPattern,
116}
117
118#[cfg(not(target_arch = "wasm32"))]
119inventory::collect!(TsainPatternDefinition);
120
121#[cfg(not(target_arch = "wasm32"))]
122pub struct TsainAliasDefinition {
123 pub __script: &'static str,
124}
125#[cfg(not(target_arch = "wasm32"))]
126inventory::collect!(TsainAliasDefinition);