Skip to content

Commit 49b811a

Browse files
[typeshare] Support external tags for enums (#7)
## Description * For complex enums the default serde serialization is externally tagged, to avoid having to re-write our rust logic to use internal tags via `#[serde(tag = "type", content = "content")]` we are going to add manual support for it in `typescript` * Bumping version to `1.12.1` * Adding a `--dry-run` flag to allow building locally ### Before ``` # Rust enum MyEnum { blahblah { name: String } blahblah2 { age: u64 } } ``` ``` # Typescript export type MyEnum = { "type": "blahblah", content: { "name": string }} | { "type": "blahblah2", content: { "age": number }} ``` ### After ``` export type MyEnum = { "blahblah": { "name": string }} | { "blahblah2": { "age": number }} ``` ## Test Plan * CI passes ## Revert Plan * Revert
1 parent a8ea230 commit 49b811a

File tree

7 files changed

+78
-39
lines changed

7 files changed

+78
-39
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ dist/
1717
uploads.txt
1818
dist-manifest.json
1919
.intentionally-empty-file.o
20+
.DS_Store

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "typeshare-cli"
3-
version = "1.12.0"
3+
version = "1.12.1"
44
edition = "2021"
55
description = "Command Line Tool for generating language files with typeshare"
66
license = "MIT OR Apache-2.0"
@@ -26,7 +26,7 @@ once_cell = "1"
2626
rayon = "1.10"
2727
serde = { version = "1", features = ["derive"] }
2828
toml = "0.8"
29-
typeshare-core = { path = "../core", version = "=1.12.0" }
29+
typeshare-core = { path = "../core", version = "=1.12.1" }
3030
log.workspace = true
3131
flexi_logger.workspace = true
3232
anyhow = "1"

core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "typeshare-core"
3-
version = "1.12.0"
3+
version = "1.12.1"
44
license = "MIT OR Apache-2.0"
55
edition = "2021"
66
description = "The code generator used by Typeshare's command line tool"

core/src/language/typescript.rs

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -216,32 +216,63 @@ impl TypeScript {
216216
writeln!(w)?;
217217
self.write_comments(w, 1, &v.shared().comments)?;
218218
match v {
219-
RustEnumVariant::Unit(shared) => write!(
220-
w,
221-
"\t| {{ {}: {:?}, {}?: undefined }}",
222-
tag_key, shared.id.renamed, content_key
223-
),
219+
RustEnumVariant::Unit(shared) => {
220+
if !tag_key.is_empty() {
221+
if !content_key.is_empty() {
222+
write!(
223+
w,
224+
"\t| {{ {}: {:?}, {}?: undefined }}",
225+
tag_key, shared.id.renamed, content_key
226+
)
227+
} else {
228+
write!(w, "\t| {{ {}: {:?} }}", tag_key, shared.id.renamed)
229+
}
230+
} else {
231+
write!(w, "\t| {:?}", shared.id.renamed)
232+
}
233+
}
224234
RustEnumVariant::Tuple { ty, shared } => {
225235
let r#type = self
226236
.format_type(ty, e.shared().generic_types.as_slice())
227237
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
228-
write!(
229-
w,
230-
"\t| {{ {}: {:?}, {}{}: {} }}",
231-
tag_key,
232-
shared.id.renamed,
233-
content_key,
234-
ty.is_optional().then_some("?").unwrap_or_default(),
235-
r#type
236-
)
238+
if !tag_key.is_empty() {
239+
if !content_key.is_empty() {
240+
write!(
241+
w,
242+
"\t| {{ {}: {:?}, {}{}: {} }}",
243+
tag_key,
244+
shared.id.renamed,
245+
content_key,
246+
ty.is_optional().then_some("?").unwrap_or_default(),
247+
r#type
248+
)
249+
} else {
250+
panic!("Tuple variants must have a content key if they have a tag key: {:?}", shared.id.original)
251+
}
252+
} else {
253+
write!(
254+
w,
255+
"\t| {{ {:?}{}: {} }}",
256+
shared.id.renamed,
257+
ty.is_optional().then_some("?").unwrap_or_default(),
258+
r#type
259+
)
260+
}
237261
}
238262
RustEnumVariant::AnonymousStruct { fields, shared } => {
239-
writeln!(
240-
w,
241-
"\t| {{ {}: {:?}, {}: {{",
242-
tag_key, shared.id.renamed, content_key
243-
)?;
244-
263+
if !tag_key.is_empty() {
264+
if !content_key.is_empty() {
265+
writeln!(
266+
w,
267+
"\t| {{ {}: {:?}, {}: {{",
268+
tag_key, shared.id.renamed, content_key
269+
)?;
270+
} else {
271+
panic!("Struct variants must have a content key if they have a tag key: {:?}", shared.id.original)
272+
}
273+
} else {
274+
writeln!(w, "\t| {{ {:?}: {{", shared.id.renamed)?;
275+
}
245276
fields.iter().try_for_each(|f| {
246277
self.write_field(w, f, e.shared().generic_types.as_slice())
247278
})?;

core/src/parser.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -391,12 +391,8 @@ pub(crate) fn parse_enum(e: &ItemEnum, target_os: &[String]) -> Result<RustItem,
391391
} else {
392392
// At least one enum variant is either a tuple or an anonymous struct
393393

394-
let tag_key = maybe_tag_key.ok_or_else(|| ParseError::SerdeTagRequired {
395-
enum_ident: original_enum_ident.clone(),
396-
})?;
397-
let content_key = maybe_content_key.ok_or_else(|| ParseError::SerdeContentRequired {
398-
enum_ident: original_enum_ident.clone(),
399-
})?;
394+
let tag_key = maybe_tag_key.unwrap_or_default();
395+
let content_key = maybe_content_key.unwrap_or_default();
400396

401397
Ok(RustItem::Enum(RustEnum::Algebraic {
402398
tag_key,

scripts/build.sh

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ function help() {
1414
echo " * \"aarch64-unknown-linux-gnu\""
1515
echo " * \"x86_64-unknown-linux-gnu\""
1616
echo " * \"x86_64-pc-windows-msvc\""
17+
echo " --dry-run Run the script without releasing"
1718
exit 0
1819
}
1920

@@ -26,6 +27,8 @@ function help() {
2627
TARGET=""
2728
# --version <version>
2829
VERSION=""
30+
# --dry-run
31+
DRY_RUN=false
2932

3033
# Parse command line arguments
3134
while [[ $# -gt 0 ]]; do
@@ -41,6 +44,10 @@ while [[ $# -gt 0 ]]; do
4144
shift
4245
shift
4346
;;
47+
--dry-run)
48+
DRY_RUN=true
49+
shift
50+
;;
4451
-h|--help)
4552
help
4653
;;
@@ -52,12 +59,12 @@ while [[ $# -gt 0 ]]; do
5259
done
5360

5461
# Check if required arguments are provided
55-
if [ -z "${TARGET}" ]; then
62+
if [[ -z "${TARGET}" ]]; then
5663
echo "Missing required argument: --target"
5764
exit 1
5865
fi
5966

60-
if [ -z "$VERSION" ]; then
67+
if [[ -z "$VERSION" ]]; then
6168
echo "Missing required argument: --version"
6269
exit 1
6370
fi
@@ -87,9 +94,13 @@ echo "{\"artifacts\": [{\"path\": \"dist/${ZIP_NAME}\"}]}" > dist-manifest.json
8794
echo "Build complete, contents of dist-manifest.json:"
8895
cat dist-manifest.json
8996

90-
# Upload to release
91-
cat dist-manifest.json | jq --raw-output ".artifacts[]?.path | select( . != null )" > uploads.txt
92-
echo "uploading..."
93-
cat uploads.txt
94-
gh release upload ${VERSION} $(cat uploads.txt)
95-
echo "uploaded!"
97+
if [[ "$DRY_RUN" == true ]]; then
98+
echo "ℹ️ Dry run, skipping release upload"
99+
else
100+
# Upload to release
101+
cat dist-manifest.json | jq --raw-output ".artifacts[]?.path | select( . != null )" > uploads.txt
102+
echo "uploading..."
103+
cat uploads.txt
104+
gh release upload ${VERSION} $(cat uploads.txt)
105+
echo "uploaded!"
106+
fi

0 commit comments

Comments
 (0)