From dcbc88788449418760853eeb29ade3cbf835714d Mon Sep 17 00:00:00 2001 From: Aumetra Weisman Date: Wed, 27 Nov 2024 14:12:01 +0100 Subject: [PATCH] Fix TypeScript codegen --- .../cw-schema-codegen/src/typescript/mod.rs | 2 +- .../templates/typescript/enum.tpl.ts | 2 +- .../templates/typescript/struct.tpl.ts | 2 +- .../snapshots/typescript__codegen_snap-2.snap | 2 +- .../snapshots/typescript__codegen_snap-3.snap | 2 +- .../snapshots/typescript__codegen_snap-5.snap | 4 +- .../snapshots/typescript__codegen_snap.snap | 2 +- .../tests/ts-e2e/src/index.ts | 3 + .../cw-schema-codegen/tests/typescript.rs | 56 +++++++++++-------- 9 files changed, 43 insertions(+), 32 deletions(-) diff --git a/packages/cw-schema-codegen/src/typescript/mod.rs b/packages/cw-schema-codegen/src/typescript/mod.rs index c2067bb5f..0628f47cb 100644 --- a/packages/cw-schema-codegen/src/typescript/mod.rs +++ b/packages/cw-schema-codegen/src/typescript/mod.rs @@ -18,7 +18,7 @@ fn expand_node_name<'a>( cw_schema::NodeType::Double => "z.number()".into(), cw_schema::NodeType::Boolean => "z.boolean()".into(), cw_schema::NodeType::String => "z.string()".into(), - cw_schema::NodeType::Integer { .. } => "z.string()".into(), + cw_schema::NodeType::Integer { .. } => "z.string().or(z.number())".into(), cw_schema::NodeType::Binary => "z.instanceof(Uint8Array)".into(), cw_schema::NodeType::Optional { inner } => { let inner = &schema.definitions[inner]; diff --git a/packages/cw-schema-codegen/templates/typescript/enum.tpl.ts b/packages/cw-schema-codegen/templates/typescript/enum.tpl.ts index 28ba77c76..92b826914 100644 --- a/packages/cw-schema-codegen/templates/typescript/enum.tpl.ts +++ b/packages/cw-schema-codegen/templates/typescript/enum.tpl.ts @@ -20,7 +20,7 @@ const {{ name }}Schema = z.union([ {% match variant.ty %} {% when TypeTemplate::Unit %} - z.object({ "{{ variant.name }}": z.void() }), + z.object({ "{{ variant.name }}": z.null() }).or(z.literal("{{ variant.name }}")), {% when TypeTemplate::Tuple with (types) %} z.object({ "{{ variant.name }}": z.tuple([{{ types|join(", ") }}]) }), {% when TypeTemplate::Named with { fields } %} diff --git a/packages/cw-schema-codegen/templates/typescript/struct.tpl.ts b/packages/cw-schema-codegen/templates/typescript/struct.tpl.ts index 639e1c57d..7b98afb51 100644 --- a/packages/cw-schema-codegen/templates/typescript/struct.tpl.ts +++ b/packages/cw-schema-codegen/templates/typescript/struct.tpl.ts @@ -13,7 +13,7 @@ import { z } from 'zod'; const {{ name }}Schema = {% match ty %} {% when TypeTemplate::Unit %} - z.void() + z.null() {% when TypeTemplate::Tuple with (types) %} z.tuple([{{ types|join(", ") }}]) {% when TypeTemplate::Named with { fields } %} diff --git a/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-2.snap b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-2.snap index f2c6c518d..da104338b 100644 --- a/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-2.snap +++ b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-2.snap @@ -14,7 +14,7 @@ import { z } from 'zod'; const UwuSchema = - z.tuple([z.string(), z.string()]) + z.tuple([z.string(), z.string().or(z.number())]) ; diff --git a/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-3.snap b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-3.snap index e01ffd038..167853d6e 100644 --- a/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-3.snap +++ b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-3.snap @@ -14,7 +14,7 @@ import { z } from 'zod'; const ÒwóSchema = - z.void() + z.null() ; diff --git a/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-5.snap b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-5.snap index a22c8912b..4b30b45a2 100644 --- a/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-5.snap +++ b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-5.snap @@ -19,7 +19,7 @@ const HeheheSchema = z.union([ */ - z.object({ "A": z.void() }), + z.object({ "A": z.null() }).or(z.literal("A")), /** @@ -27,7 +27,7 @@ const HeheheSchema = z.union([ */ - z.object({ "B": z.tuple([z.string()]) }), + z.object({ "B": z.tuple([z.string().or(z.number())]) }), /** diff --git a/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap.snap b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap.snap index cd3b7d47c..83e4dae1e 100644 --- a/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap.snap +++ b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap.snap @@ -20,7 +20,7 @@ const OwoSchema = */ - field_1: z.string(), + field_1: z.string().or(z.number()), /** diff --git a/packages/cw-schema-codegen/tests/ts-e2e/src/index.ts b/packages/cw-schema-codegen/tests/ts-e2e/src/index.ts index 3c976dc7b..00ecd472c 100644 --- a/packages/cw-schema-codegen/tests/ts-e2e/src/index.ts +++ b/packages/cw-schema-codegen/tests/ts-e2e/src/index.ts @@ -14,6 +14,9 @@ const typeName = process.argv[2]; const deserialized = JSON.parse(stdinString); let validated = gen[typeName].parse(deserialized); +console.error(stdinString); +console.error(deserialized); +console.error(validated); const outputStream = process.stdout; outputStream.write(JSON.stringify(validated)); diff --git a/packages/cw-schema-codegen/tests/typescript.rs b/packages/cw-schema-codegen/tests/typescript.rs index 50427b04b..0400a090e 100644 --- a/packages/cw-schema-codegen/tests/typescript.rs +++ b/packages/cw-schema-codegen/tests/typescript.rs @@ -1,4 +1,5 @@ use arbitrary::Arbitrary; +use core::str; use cw_schema::Schemaifier; use serde::{Deserialize, Serialize}; use std::{ @@ -19,15 +20,8 @@ struct Uwu(String, u32); #[derive(Arbitrary, Schemaifier, Debug, Deserialize, PartialEq, Serialize)] struct Òwó; -mod empty { - #![allow(unreachable_code)] - use super::*; - - #[derive(Arbitrary, Schemaifier, Debug, Deserialize, PartialEq, Serialize)] - pub enum Empty {} -} - -use self::empty::Empty; +#[derive(Schemaifier, Debug, Deserialize, PartialEq, Serialize)] +pub enum Empty {} #[derive(Arbitrary, Schemaifier, Debug, Deserialize, PartialEq, Serialize)] enum Hehehe { @@ -84,8 +78,7 @@ fn codegen_snap() { .iter() .map(|node| { let mut buf = Vec::new(); - cw_schema_codegen::typescript::process_node(&mut buf, &schema, node, true) - .unwrap(); + cw_schema_codegen::typescript::process_node(&mut buf, &schema, node, true).unwrap(); String::from_utf8(buf).unwrap() }) .collect::(); @@ -124,11 +117,12 @@ fn assert_validity() { wrap::<Òwó>, type_name::<Òwó>(), ), - ( + // `Empty` is a non-constructable type + /*( cw_schema::schema_of::(), wrap::, type_name::(), - ), + ),*/ ( cw_schema::schema_of::(), wrap::, @@ -136,6 +130,17 @@ fn assert_validity() { ), ]; + let e2e_dir = format!("{}/tests/ts-e2e", env!("CARGO_MANIFEST_DIR")); + let gen_file_path = format!("{}/src/gen.ts", e2e_dir); + + // make sure the dependencies are installed + let install_status = Command::new("npm") + .arg("i") + .current_dir(&e2e_dir) + .status() + .unwrap(); + assert!(install_status.success()); + let random_data: [u8; 255] = rand::random(); let mut unstructured = arbitrary::Unstructured::new(&random_data); for (schema, arbitrary_gen, type_name) in schemas { @@ -148,26 +153,20 @@ fn assert_validity() { .iter() .map(|node| { let mut buf = Vec::new(); - cw_schema_codegen::typescript::process_node(&mut buf, schema, node, true) - .unwrap(); + cw_schema_codegen::typescript::process_node(&mut buf, schema, node, true).unwrap(); String::from_utf8(buf).unwrap() }) .collect::(); - let e2e_dir = format!("{}/tests/ts-e2e", env!("CARGO_MANIFEST_DIR")); - let gen_file_path = format!("{}/src/gen.ts", e2e_dir); - let mut gen_file = File::create(gen_file_path).unwrap(); + let mut gen_file = File::create(&gen_file_path).unwrap(); gen_file.write_all(output.as_bytes()).unwrap(); let data = arbitrary_gen(&mut unstructured); let serialized = serde_json::to_string(&data).unwrap(); - let install_status = Command::new("npm").arg("i").current_dir(&e2e_dir).status().unwrap(); - assert!(install_status.success()); - let mut child = Command::new("npm") .args(["test", type_name]) - .current_dir(e2e_dir) + .current_dir(&e2e_dir) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() @@ -178,8 +177,17 @@ fn assert_validity() { stdin.write_all(serialized.as_bytes()).unwrap(); } - let output = child.wait_with_output().unwrap(); - let deserialized: Combined = serde_json::from_slice(&output.stdout).unwrap(); + let proc_output = child.wait_with_output().unwrap(); + assert!( + proc_output.status.success(), + "failed with object: {data:#?}; json: {serialized}; schema: {output}" + ); + + let stdout = str::from_utf8(&proc_output.stdout).unwrap(); + let stdout = stdout.lines().last().unwrap(); + let deserialized: Combined = serde_json::from_str(stdout).unwrap_or_else(|err| { + panic!("{err:?}; input: {serialized}, output: {stdout}"); + }); assert_eq!(data, deserialized); }