diff --git a/.circleci/config.yml b/.circleci/config.yml index fb483cf30c..427677b8de 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,10 @@ version: 2.1 orbs: + go: circleci/go@3.0.2 + node: circleci/node@7.1.0 + python: circleci/python@3.0.0 + rust: circleci/rust@1.7.0 win: circleci/windows@5.1 commands: @@ -71,6 +75,7 @@ workflows: - package_schema - package_schema_derive - package_cw_schema + - package_cw_schema_codegen - package_std - package_vm - package_vm_derive @@ -447,6 +452,42 @@ jobs: - target/debug/deps key: cargocache-v2-package_cw_schema-rust:1.82-{{ checksum "Cargo.lock" }} + package_cw_schema_codegen: + executor: + name: python/default + steps: + - checkout + - rust/install: + version: "1.86" + - run: + name: Version information + command: rustc --version; cargo --version; rustup --version; rustup target list --installed + - restore_cache: + keys: + - cargocache-v2-package_cw_schema_codegen-rust:1.86-{{ checksum "Cargo.lock" }} + - go/install: + version: 1.23.4 + - node/install + - run: + name: Install pydantic + command: pip install pydantic + - run: + name: Build + working_directory: ~/project/packages/cw-schema-codegen + command: cargo build --locked + - run: + name: Run tests + working_directory: ~/project/packages/cw-schema-codegen + # Use --include-ignored to also run ignored tests + command: cargo test --locked -- --include-ignored + - save_cache: + paths: + - /usr/local/cargo/registry + - target/debug/.fingerprint + - target/debug/build + - target/debug/deps + key: cargocache-v2-package_cw_schema_codegen-rust:1.86-{{ checksum "Cargo.lock" }} + package_std: docker: - image: rust:1.82 @@ -1248,7 +1289,7 @@ jobs: coverage: docker: - - image: rust:1.84.1-alpine3.21 + - image: rust:1.86-alpine3.21 resource_class: medium+ steps: - checkout @@ -1257,7 +1298,8 @@ jobs: command: | apk update # needed for grcov and compiling tests - apk add --no-cache mold clang curl llvm19-dev clang19-static lcov + apk add --no-cache mold clang curl llvm19-dev clang19-static lcov python3 py3-pip py3-pydantic nodejs npm + ln -sf python3 /usr/bin/python - run: name: Install cargo-llvm-cov and cargo-nextest command: | @@ -1277,11 +1319,16 @@ jobs: command: | curl -L --proto '=https' --tlsv1.2 -OsSf https://cli.codecov.io/v10.1.1/alpine/codecov chmod +x codecov + - go/install: + version: 1.23.4 + - run: + name: Install pydantic + command: pip install pydantic --break-system-packages - run: name: Run tests with coverage command: | # Generate full coverage report - cargo llvm-cov nextest --all-features --lcov --output-path lcov.info + cargo llvm-cov nextest --all-features --run-ignored=all --lcov --output-path lcov.info # List of package directories and their flags # ToDo: Re-add "core:cosmwasm-core" when enabling core coverage again @@ -1293,7 +1340,9 @@ jobs: "schema-derive:cosmwasm-schema-derive" \ "std:cosmwasm-std" \ "vm:cosmwasm-vm" \ - "vm-derive:cosmwasm-vm-derive" + "vm-derive:cosmwasm-vm-derive" \ + "cw-schema:cw-schema" \ + "cw-schema-codegen:cw-schema-codegen" # Process each package-flag pair for entry in "$@"; do diff --git a/Cargo.lock b/Cargo.lock index ec918f5f16..da2b52092f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,6 +106,15 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "ark-bls12-381" version = "0.5.0" @@ -241,6 +250,45 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "askama" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28" +dependencies = [ + "askama_derive", + "askama_escape", +] + +[[package]] +name = "askama_derive" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83" +dependencies = [ + "askama_parser", + "mime", + "mime_guess", + "proc-macro2", + "quote", + "syn 2.0.103", +] + +[[package]] +name = "askama_escape" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" + +[[package]] +name = "askama_parser" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0" +dependencies = [ + "nom", +] + [[package]] name = "assert_cmd" version = "2.0.17" @@ -526,6 +574,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", + "clap_derive", ] [[package]] @@ -540,6 +589,18 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_derive" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.103", +] + [[package]] name = "clap_lex" version = "0.7.5" @@ -939,6 +1000,29 @@ dependencies = [ "typeid", ] +[[package]] +name = "cw-schema-codegen" +version = "3.0.1" +dependencies = [ + "anyhow", + "arbitrary", + "askama", + "clap", + "cosmwasm-schema", + "cosmwasm-std", + "cw-schema", + "derive_arbitrary", + "either", + "heck", + "insta", + "log", + "rand 0.8.5", + "serde", + "serde_json", + "simple_logger", + "tempfile", +] + [[package]] name = "cw-schema-derive" version = "3.0.1" @@ -1019,6 +1103,17 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", +] + [[package]] name = "derive_more" version = "0.99.20" @@ -1878,6 +1973,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1975,6 +2086,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.32.2" @@ -2898,6 +3018,18 @@ version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" +[[package]] +name = "simple_logger" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c5dfa5e08767553704aa0ffd9d9794d527103c736aba9854773851fd7497eb" +dependencies = [ + "colored", + "log", + "time", + "windows-sys 0.48.0", +] + [[package]] name = "siphasher" version = "1.0.1" @@ -3078,7 +3210,9 @@ checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -3195,6 +3329,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -3622,6 +3762,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -3649,6 +3798,21 @@ dependencies = [ "windows-targets 0.53.2", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -3681,6 +3845,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -3693,6 +3863,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -3705,6 +3881,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3729,6 +3911,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -3741,6 +3929,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -3753,6 +3947,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -3765,6 +3965,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index e9e7c4c2f3..24175efe7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,9 @@ [workspace] members = ["packages/*"] -exclude = ["contracts"] +exclude = [ + "contracts", + "packages/cw-schema-codegen/tests/rust-e2e", +] # Resolver has to be set explicitly in workspaces # due to https://github.com/rust-lang/cargo/issues/9956 diff --git a/codecov.yml b/codecov.yml index c6cf455fde..8b11d6b546 100644 --- a/codecov.yml +++ b/codecov.yml @@ -40,3 +40,10 @@ flags: cosmwasm-vm-derive: paths: - packages/vm-derive/ + + cw-schema: + paths: + - packages/cw-schema + cw-schema-codegen: + paths: + - packages/cw-schema-codegen diff --git a/packages/cw-schema-codegen/Cargo.toml b/packages/cw-schema-codegen/Cargo.toml new file mode 100644 index 0000000000..2f8ea37c3e --- /dev/null +++ b/packages/cw-schema-codegen/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "cw-schema-codegen" +authors = ["Aumetra Weisman "] +edition = "2021" +version.workspace = true +description = "A code generator for CosmWasm contracts to generate code for other languages from schema files." +repository = "https://github.com/CosmWasm/cosmwasm/tree/main/packages/cw-schema-codegen" +license = "Apache-2.0" +build = "build.rs" + +[dependencies] +anyhow = "1.0.89" +askama = { version = "0.12.1", default-features = false } +clap = { version = "4.5.18", features = ["derive"] } +cosmwasm-schema = { version = "=3.0.1", path = "../schema" } +cw-schema = { version = "=3.0.1", path = "../cw-schema" } +either = "1.13.0" +heck = "0.5.0" +log = "0.4.22" +serde_json = "1.0.128" +simple_logger = { version = "5.0.0", features = ["stderr"] } + +[dev-dependencies] +arbitrary = { version = "=1.3.2", features = ["derive"] } +derive_arbitrary = "=1.3.2" +insta = "1.40.0" +rand = { version = "0.8.5", features = ["min_const_gen"] } +serde = { workspace = true, features = ["derive"] } +serde_json = "1.0.128" +tempfile = "3.14.0" +cosmwasm-std = { version = "3.0.1", path = "../std", default-features = false, features = [ + "std", +] } diff --git a/packages/cw-schema-codegen/build.rs b/packages/cw-schema-codegen/build.rs new file mode 100644 index 0000000000..73f98cda43 --- /dev/null +++ b/packages/cw-schema-codegen/build.rs @@ -0,0 +1,3 @@ +fn main() { + println!("cargo:rerun-if-changed=templates"); +} diff --git a/packages/cw-schema-codegen/src/go/mod.rs b/packages/cw-schema-codegen/src/go/mod.rs new file mode 100644 index 0000000000..5caf83b99a --- /dev/null +++ b/packages/cw-schema-codegen/src/go/mod.rs @@ -0,0 +1,172 @@ +use self::template::{ + EnumTemplate, EnumVariantTemplate, FieldTemplate, StructTemplate, TypeTemplate, +}; +use heck::ToPascalCase; +use std::{borrow::Cow, io}; + +pub mod template; + +fn expand_node_name<'a>( + schema: &'a cw_schema::SchemaV1, + node: &'a cw_schema::Node, +) -> Cow<'a, str> { + match node.value { + cw_schema::NodeType::Array { items } => { + let items = &schema.definitions[items]; + format!("[]{}", expand_node_name(schema, items)).into() + } + cw_schema::NodeType::Float => "float32".into(), + cw_schema::NodeType::Double => "float64".into(), + cw_schema::NodeType::Boolean => "bool".into(), + cw_schema::NodeType::String => "string".into(), + cw_schema::NodeType::Integer { signed, precision } => { + let ty = if signed { "int" } else { "uint" }; + format!("{ty}{precision}").into() + } + cw_schema::NodeType::Binary => "[]byte".into(), + + cw_schema::NodeType::Boxed { inner } => { + let node = &schema.definitions[inner]; + expand_node_name(schema, node) + } + cw_schema::NodeType::Optional { inner } => { + let inner = &schema.definitions[inner]; + format!("{}", expand_node_name(schema, inner)).into() + } + + cw_schema::NodeType::Map { key, value, .. } => { + let key = expand_node_name(schema, &schema.definitions[key]); + let value = expand_node_name(schema, &schema.definitions[value]); + + format!("map[{key}]{value}").into() + } + cw_schema::NodeType::Struct(..) => node.name.as_ref().into(), + cw_schema::NodeType::Tuple { ref items } => { + if items.len() == 1 { + expand_node_name(schema, &schema.definitions[items[0]]) + } else { + "[]interface{}".into() + } + } + cw_schema::NodeType::Enum { .. } => node.name.as_ref().into(), + + cw_schema::NodeType::Decimal { + precision: _, + signed: _, + } => { + // ToDo: Actually use a decimal type here + "string".into() + } + cw_schema::NodeType::Address => "Address".into(), + cw_schema::NodeType::Checksum => "string".into(), + cw_schema::NodeType::HexBinary => { + // ToDo: Actually use a hex-encoded binary type here + "string".into() + } + cw_schema::NodeType::Timestamp => "string".into(), + cw_schema::NodeType::Unit => "struct{}".into(), + } +} + +fn prepare_docs(desc: Option<&str>) -> Cow<'_, [Cow<'_, str>]> { + desc.map(|desc| { + desc.lines() + .map(|line| line.replace('"', "\\\"").into()) + .collect() + }) + .unwrap_or(Cow::Borrowed(&[])) +} + +pub fn process_node( + output: &mut O, + schema: &cw_schema::SchemaV1, + node: &cw_schema::Node, + add_package: bool, +) -> io::Result<()> +where + O: io::Write, +{ + match node.value { + cw_schema::NodeType::Struct(ref sty) => { + let structt = StructTemplate { + add_package, + name: node.name.clone(), + docs: prepare_docs(node.description.as_deref()), + ty: match sty { + cw_schema::StructType::Unit => TypeTemplate::Unit, + cw_schema::StructType::Named { ref properties } => TypeTemplate::Named { + fields: properties + .iter() + .map(|(name, prop)| FieldTemplate { + name: Cow::Owned(name.to_pascal_case()), + rename: Cow::Borrowed(name), + docs: prepare_docs(prop.description.as_deref()), + ty: expand_node_name(schema, &schema.definitions[prop.value]), + }) + .collect(), + }, + cw_schema::StructType::Tuple { ref items } => TypeTemplate::Tuple( + items + .iter() + .map(|item| expand_node_name(schema, &schema.definitions[*item])) + .collect(), + ), + }, + }; + + writeln!(output, "{structt}")?; + } + cw_schema::NodeType::Enum { ref cases, .. } => { + let enumm = EnumTemplate { + add_package, + name: node.name.clone(), + docs: prepare_docs(node.description.as_deref()), + variants: cases + .iter() + .map(|(name, case)| EnumVariantTemplate { + name: name.to_pascal_case().into(), + rename: Cow::Borrowed(name), + docs: prepare_docs(case.description.as_deref()), + ty: match case.value { + cw_schema::EnumValue::Unit => TypeTemplate::Unit, + cw_schema::EnumValue::Tuple { ref items } => { + let items = items + .iter() + .map(|item| { + expand_node_name(schema, &schema.definitions[*item]) + }) + .collect(); + + TypeTemplate::Tuple(items) + } + cw_schema::EnumValue::Named { ref properties, .. } => { + TypeTemplate::Named { + fields: properties + .iter() + .map(|(name, prop)| FieldTemplate { + name: Cow::Owned(name.to_pascal_case()), + rename: Cow::Borrowed(name), + docs: prepare_docs(prop.description.as_deref()), + ty: expand_node_name( + schema, + &schema.definitions[prop.value], + ), + }) + .collect(), + } + } + }, + }) + .collect(), + has_unit_variants: cases + .iter() + .any(|(_, case)| matches!(case.value, cw_schema::EnumValue::Unit)), + }; + + writeln!(output, "{enumm}")?; + } + _ => (), + } + + Ok(()) +} diff --git a/packages/cw-schema-codegen/src/go/template.rs b/packages/cw-schema-codegen/src/go/template.rs new file mode 100644 index 0000000000..4c2f533627 --- /dev/null +++ b/packages/cw-schema-codegen/src/go/template.rs @@ -0,0 +1,52 @@ +use askama::Template; +use std::borrow::Cow; + +#[derive(Clone)] +pub struct EnumVariantTemplate<'a> { + pub name: Cow<'a, str>, + pub rename: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: TypeTemplate<'a>, +} + +#[derive(Template)] +#[template(escape = "none", path = "go/enum.tpl.go")] +pub struct EnumTemplate<'a> { + pub add_package: bool, + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub variants: Cow<'a, [EnumVariantTemplate<'a>]>, + pub has_unit_variants: bool, +} + +#[derive(Clone)] +pub struct FieldTemplate<'a> { + pub name: Cow<'a, str>, + pub rename: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: Cow<'a, str>, +} + +#[derive(Clone)] +pub enum TypeTemplate<'a> { + Unit, + Tuple(Cow<'a, [Cow<'a, str>]>), + Named { + fields: Cow<'a, [FieldTemplate<'a>]>, + }, +} + +impl TypeTemplate<'_> { + pub fn is_unit(&self) -> bool { + matches!(self, TypeTemplate::Unit) + } +} + +#[derive(Template)] +#[template(escape = "none", path = "go/struct.tpl.go")] +pub struct StructTemplate<'a> { + pub add_package: bool, + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: TypeTemplate<'a>, +} diff --git a/packages/cw-schema-codegen/src/lib.rs b/packages/cw-schema-codegen/src/lib.rs new file mode 100644 index 0000000000..224f90fb84 --- /dev/null +++ b/packages/cw-schema-codegen/src/lib.rs @@ -0,0 +1,4 @@ +pub mod go; +pub mod python; +pub mod rust; +pub mod typescript; diff --git a/packages/cw-schema-codegen/src/main.rs b/packages/cw-schema-codegen/src/main.rs new file mode 100644 index 0000000000..b116ca0d8c --- /dev/null +++ b/packages/cw-schema-codegen/src/main.rs @@ -0,0 +1,138 @@ +#[macro_use] +extern crate anyhow; + +#[macro_use] +extern crate log; + +use clap::{Parser, ValueEnum}; +use std::{ + collections::HashSet, + fs::{self, File}, + io::{self, Write}, + path::PathBuf, +}; + +#[derive(Clone, Copy, Debug, Default, PartialEq, ValueEnum)] +pub enum Language { + #[default] + Rust, + Go, + Python, + Typescript, +} + +#[derive(Parser)] +#[clap(about, author, version)] +/// Official CosmWasm codegen tool +struct Opts { + #[clap(default_value_t, long, short, value_enum)] + /// Programming language to generate code for + language: Language, + + #[clap(long, short)] + /// Path to the schema file + file: PathBuf, + + #[clap(long, short)] + /// Path to the output file + output: Option, +} + +impl Opts { + fn output(&self) -> anyhow::Result { + let io_out = if let Some(ref path) = self.output { + either::Left(File::create(path)?) + } else { + either::Right(io::stdout().lock()) + }; + + Ok(io_out) + } +} + +fn generate_defs( + output: &mut W, + language: Language, + schema: &cw_schema::Schema, + add_heading_stuff: bool, +) -> anyhow::Result<()> +where + W: io::Write, +{ + let cw_schema::Schema::V1(schema) = schema else { + bail!("Only schema version 1 is supported") + }; + + schema.definitions.iter().rev().try_for_each(|node| { + debug!("Processing node: {node:?}"); + + match language { + Language::Rust => { + cw_schema_codegen::rust::process_node(output, schema, node, add_heading_stuff) + } + Language::Typescript => { + cw_schema_codegen::typescript::process_node(output, schema, node, add_heading_stuff) + } + Language::Python => cw_schema_codegen::python::process_node(output, schema, node), + Language::Go => { + cw_schema_codegen::go::process_node(output, schema, node, add_heading_stuff) + } + } + })?; + + Ok(()) +} + +fn main() -> anyhow::Result<()> { + simple_logger::SimpleLogger::new() + .without_timestamps() + .with_level(log::LevelFilter::Info) + .env() + .init()?; + + let opts: Opts = Opts::parse(); + info!( + "Generating code for {:?} from {:?}", + opts.language, opts.file + ); + + ensure!(opts.file.exists(), "Schema file does not exist"); + + let schema = fs::read_to_string(&opts.file)?; + let schema: cosmwasm_schema::JsonCwApi = serde_json::from_str(&schema)?; + + let mut output = opts.output()?; + + if let Some(ref instantiate) = schema.instantiate { + generate_defs(&mut output, opts.language, instantiate, true)?; + } + + if let Some(ref execute) = schema.execute { + generate_defs(&mut output, opts.language, execute, false)?; + } + + if let Some(ref query) = schema.query { + generate_defs(&mut output, opts.language, query, false)?; + } + + if let Some(ref migrate) = schema.migrate { + generate_defs(&mut output, opts.language, migrate, false)?; + } + + if let Some(ref sudo) = schema.sudo { + generate_defs(&mut output, opts.language, sudo, false)?; + } + + if let Some(ref responses) = schema.responses { + let responses = responses + .iter() + .map(|(_name, response)| response) + .collect::>(); + + for response in responses { + generate_defs(&mut output, opts.language, response, false)?; + } + } + + Ok(()) +} diff --git a/packages/cw-schema-codegen/src/python/mod.rs b/packages/cw-schema-codegen/src/python/mod.rs new file mode 100644 index 0000000000..e9f1b877ad --- /dev/null +++ b/packages/cw-schema-codegen/src/python/mod.rs @@ -0,0 +1,147 @@ +use self::template::{ + EnumTemplate, EnumVariantTemplate, FieldTemplate, StructTemplate, TypeTemplate, +}; +use std::{borrow::Cow, io}; + +pub mod template; + +fn expand_node_name<'a>( + schema: &'a cw_schema::SchemaV1, + node: &'a cw_schema::Node, +) -> Cow<'a, str> { + match node.value { + cw_schema::NodeType::Array { items } => { + let items = &schema.definitions[items]; + format!("typing.List[{}]", expand_node_name(schema, items)).into() + } + cw_schema::NodeType::Float => "float".into(), + cw_schema::NodeType::Double => "float".into(), + cw_schema::NodeType::Boolean => "bool".into(), + cw_schema::NodeType::String => "str".into(), + cw_schema::NodeType::Integer { .. } => "int".into(), + cw_schema::NodeType::Binary => "Base64Bytes".into(), + + cw_schema::NodeType::Boxed { inner } => { + let node = &schema.definitions[inner]; + expand_node_name(schema, node) + } + cw_schema::NodeType::Optional { inner } => { + let inner = &schema.definitions[inner]; + format!("typing.Optional[{}]", expand_node_name(schema, inner)).into() + } + + cw_schema::NodeType::Map { key, value, .. } => { + let key = expand_node_name(schema, &schema.definitions[key]); + let value = expand_node_name(schema, &schema.definitions[value]); + + format!("typing.Dict[{key}, {value}]").into() + } + cw_schema::NodeType::Struct(..) => node.name.as_ref().into(), + cw_schema::NodeType::Tuple { ref items } => { + let items = items + .iter() + .map(|item| expand_node_name(schema, &schema.definitions[*item])) + .collect::>() + .join(", "); + + format!("typing.Tuple[{}]", items).into() + } + cw_schema::NodeType::Enum { .. } => node.name.as_ref().into(), + cw_schema::NodeType::Decimal { .. } => "decimal.Decimal".into(), + cw_schema::NodeType::Address => "str".into(), + cw_schema::NodeType::Checksum => "str".into(), + cw_schema::NodeType::HexBinary => "str".into(), + cw_schema::NodeType::Timestamp => "str".into(), + cw_schema::NodeType::Unit => "None".into(), + } +} + +fn prepare_docs(desc: Option<&str>) -> Cow<'_, [Cow<'_, str>]> { + desc.map(|desc| desc.lines().map(Into::into).collect()) + .unwrap_or(Cow::Borrowed(&[])) +} + +pub fn process_node( + output: &mut O, + schema: &cw_schema::SchemaV1, + node: &cw_schema::Node, +) -> io::Result<()> +where + O: io::Write, +{ + match node.value { + cw_schema::NodeType::Struct(ref sty) => { + let structt = StructTemplate { + name: node.name.clone(), + docs: prepare_docs(node.description.as_deref()), + ty: match sty { + cw_schema::StructType::Unit => TypeTemplate::Unit, + cw_schema::StructType::Named { ref properties } => TypeTemplate::Named { + fields: properties + .iter() + .map(|(name, prop)| FieldTemplate { + name: Cow::Borrowed(name), + docs: prepare_docs(prop.description.as_deref()), + ty: expand_node_name(schema, &schema.definitions[prop.value]), + }) + .collect(), + }, + cw_schema::StructType::Tuple { ref items } => TypeTemplate::Tuple( + items + .iter() + .map(|item| expand_node_name(schema, &schema.definitions[*item])) + .collect(), + ), + }, + }; + + writeln!(output, "{structt}")?; + } + cw_schema::NodeType::Enum { ref cases, .. } => { + let enumm = EnumTemplate { + name: node.name.clone(), + docs: prepare_docs(node.description.as_deref()), + variants: cases + .iter() + .map(|(name, case)| EnumVariantTemplate { + name: name.clone(), + docs: prepare_docs(case.description.as_deref()), + ty: match case.value { + cw_schema::EnumValue::Unit => TypeTemplate::Unit, + cw_schema::EnumValue::Tuple { ref items } => { + let items = items + .iter() + .map(|item| { + expand_node_name(schema, &schema.definitions[*item]) + }) + .collect(); + + TypeTemplate::Tuple(items) + } + cw_schema::EnumValue::Named { ref properties, .. } => { + TypeTemplate::Named { + fields: properties + .iter() + .map(|(name, prop)| FieldTemplate { + name: Cow::Borrowed(name), + docs: prepare_docs(prop.description.as_deref()), + ty: expand_node_name( + schema, + &schema.definitions[prop.value], + ), + }) + .collect(), + } + } + }, + }) + .collect(), + }; + + writeln!(output, "{enumm}")?; + } + _ => (), + } + + Ok(()) +} diff --git a/packages/cw-schema-codegen/src/python/template.rs b/packages/cw-schema-codegen/src/python/template.rs new file mode 100644 index 0000000000..11b860ed92 --- /dev/null +++ b/packages/cw-schema-codegen/src/python/template.rs @@ -0,0 +1,41 @@ +use askama::Template; +use std::borrow::Cow; + +#[derive(Clone)] +pub struct EnumVariantTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: TypeTemplate<'a>, +} + +#[derive(Template)] +#[template(escape = "none", path = "python/enum.tpl.py")] +pub struct EnumTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub variants: Cow<'a, [EnumVariantTemplate<'a>]>, +} + +#[derive(Clone)] +pub struct FieldTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: Cow<'a, str>, +} + +#[derive(Clone)] +pub enum TypeTemplate<'a> { + Unit, + Tuple(Cow<'a, [Cow<'a, str>]>), + Named { + fields: Cow<'a, [FieldTemplate<'a>]>, + }, +} + +#[derive(Template)] +#[template(escape = "none", path = "python/struct.tpl.py")] +pub struct StructTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: TypeTemplate<'a>, +} diff --git a/packages/cw-schema-codegen/src/rust/mod.rs b/packages/cw-schema-codegen/src/rust/mod.rs new file mode 100644 index 0000000000..ab3b3095a5 --- /dev/null +++ b/packages/cw-schema-codegen/src/rust/mod.rs @@ -0,0 +1,186 @@ +use self::template::{ + EnumTemplate, EnumVariantTemplate, FieldTemplate, StructTemplate, TypeTemplate, +}; +use heck::ToPascalCase; +use std::{borrow::Cow, io}; + +pub mod template; + +fn expand_node_name<'a>( + schema: &'a cw_schema::SchemaV1, + node: &'a cw_schema::Node, +) -> Cow<'a, str> { + match node.value { + cw_schema::NodeType::Array { items } => { + let items = &schema.definitions[items]; + format!("Vec<{}>", expand_node_name(schema, items)).into() + } + cw_schema::NodeType::Float => "f32".into(), + cw_schema::NodeType::Double => "f64".into(), + cw_schema::NodeType::Boolean => "bool".into(), + cw_schema::NodeType::String => "String".into(), + cw_schema::NodeType::Integer { signed, precision } => { + let ty = if signed { "i" } else { "u" }; + format!("{ty}{precision}").into() + } + cw_schema::NodeType::Binary => "String".into(), // ToDo: Use a base64 binary type + + cw_schema::NodeType::Boxed { inner } => { + let inner = &schema.definitions[inner]; + format!("::alloc::boxed::Box<{}>", expand_node_name(schema, inner)).into() + } + cw_schema::NodeType::Optional { inner } => { + let inner = &schema.definitions[inner]; + format!( + "::core::option::Option<{}>", + expand_node_name(schema, inner) + ) + .into() + } + + cw_schema::NodeType::Map { + ref kind, + key, + value, + } => { + let key = expand_node_name(schema, &schema.definitions[key]); + let value = expand_node_name(schema, &schema.definitions[value]); + + match kind { + cw_schema::MapKind::BTree => { + format!("::alloc::collections::BTreeMap<{key}, {value}>") + } + cw_schema::MapKind::Hash => format!("::std::collections::HashMap<{key}, {value}>"), + _ => unimplemented!(), + } + .into() + } + cw_schema::NodeType::Struct(..) => node.name.as_ref().into(), + cw_schema::NodeType::Tuple { ref items } => { + let items = items + .iter() + .map(|item| expand_node_name(schema, &schema.definitions[*item])) + .collect::>() + .join(", "); + + format!("({})", items).into() + } + cw_schema::NodeType::Enum { .. } => node.name.as_ref().into(), + + cw_schema::NodeType::Decimal { + precision: _, + signed: _, + } => { + // ToDo: Actually use a decimal type here + "String".into() + } + cw_schema::NodeType::Address => "cosmrs::AccountId".into(), + cw_schema::NodeType::Checksum => "cosmrs::tendermint::Hash".into(), + cw_schema::NodeType::HexBinary => { + // ToDo: Actually use a hex-encoded binary type here + "String".into() + } + cw_schema::NodeType::Timestamp => "cosmrs::tendermint::Time".into(), + cw_schema::NodeType::Unit => "()".into(), + } +} + +fn prepare_docs(desc: Option<&str>) -> Cow<'_, [Cow<'_, str>]> { + desc.map(|desc| { + desc.lines() + .map(|line| line.replace('"', "\\\"").into()) + .collect() + }) + .unwrap_or(Cow::Borrowed(&[])) +} + +pub fn process_node( + output: &mut O, + schema: &cw_schema::SchemaV1, + node: &cw_schema::Node, + add_allow: bool, +) -> io::Result<()> +where + O: io::Write, +{ + match node.value { + cw_schema::NodeType::Struct(ref sty) => { + let structt = StructTemplate { + add_allow, + name: node.name.clone(), + docs: prepare_docs(node.description.as_deref()), + ty: match sty { + cw_schema::StructType::Unit => TypeTemplate::Unit, + cw_schema::StructType::Named { ref properties } => TypeTemplate::Named { + fields: properties + .iter() + .map(|(name, prop)| FieldTemplate { + name: Cow::Borrowed(name), + defaulting: prop.defaulting, + docs: prepare_docs(prop.description.as_deref()), + ty: expand_node_name(schema, &schema.definitions[prop.value]), + }) + .collect(), + }, + cw_schema::StructType::Tuple { ref items } => TypeTemplate::Tuple( + items + .iter() + .map(|item| expand_node_name(schema, &schema.definitions[*item])) + .collect(), + ), + }, + }; + + writeln!(output, "{structt}")?; + } + cw_schema::NodeType::Enum { ref cases, .. } => { + let enumm = EnumTemplate { + add_allow, + name: node.name.clone(), + docs: prepare_docs(node.description.as_deref()), + variants: cases + .iter() + .map(|(name, case)| EnumVariantTemplate { + name: name.to_pascal_case().into(), + docs: prepare_docs(case.description.as_deref()), + serde_rename: Some(name.clone()), + ty: match case.value { + cw_schema::EnumValue::Unit => TypeTemplate::Unit, + cw_schema::EnumValue::Tuple { ref items } => { + let items = items + .iter() + .map(|item| { + expand_node_name(schema, &schema.definitions[*item]) + }) + .collect(); + + TypeTemplate::Tuple(items) + } + cw_schema::EnumValue::Named { ref properties, .. } => { + TypeTemplate::Named { + fields: properties + .iter() + .map(|(name, prop)| FieldTemplate { + name: Cow::Borrowed(name), + defaulting: prop.defaulting, + docs: prepare_docs(prop.description.as_deref()), + ty: expand_node_name( + schema, + &schema.definitions[prop.value], + ), + }) + .collect(), + } + } + }, + }) + .collect(), + }; + + writeln!(output, "{enumm}")?; + } + _ => (), + } + + Ok(()) +} diff --git a/packages/cw-schema-codegen/src/rust/template.rs b/packages/cw-schema-codegen/src/rust/template.rs new file mode 100644 index 0000000000..8c63f4adb4 --- /dev/null +++ b/packages/cw-schema-codegen/src/rust/template.rs @@ -0,0 +1,45 @@ +use askama::Template; +use std::borrow::Cow; + +#[derive(Clone)] +pub struct EnumVariantTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub serde_rename: Option>, + pub ty: TypeTemplate<'a>, +} + +#[derive(Template)] +#[template(escape = "none", path = "rust/enum.tpl.rs")] +pub struct EnumTemplate<'a> { + pub add_allow: bool, + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub variants: Cow<'a, [EnumVariantTemplate<'a>]>, +} + +#[derive(Clone)] +pub struct FieldTemplate<'a> { + pub name: Cow<'a, str>, + pub defaulting: bool, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: Cow<'a, str>, +} + +#[derive(Clone)] +pub enum TypeTemplate<'a> { + Unit, + Tuple(Cow<'a, [Cow<'a, str>]>), + Named { + fields: Cow<'a, [FieldTemplate<'a>]>, + }, +} + +#[derive(Template)] +#[template(escape = "none", path = "rust/struct.tpl.rs")] +pub struct StructTemplate<'a> { + pub add_allow: bool, + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: TypeTemplate<'a>, +} diff --git a/packages/cw-schema-codegen/src/typescript/mod.rs b/packages/cw-schema-codegen/src/typescript/mod.rs new file mode 100644 index 0000000000..8d25867efa --- /dev/null +++ b/packages/cw-schema-codegen/src/typescript/mod.rs @@ -0,0 +1,160 @@ +use self::template::{ + EnumTemplate, EnumVariantTemplate, FieldTemplate, StructTemplate, TypeTemplate, +}; +use std::{borrow::Cow, io}; + +pub mod template; + +fn expand_node_name<'a>( + schema: &'a cw_schema::SchemaV1, + node: &'a cw_schema::Node, +) -> Cow<'a, str> { + match node.value { + cw_schema::NodeType::Array { items } => { + let items = &schema.definitions[items]; + format!("z.array({})", expand_node_name(schema, items)).into() + } + cw_schema::NodeType::Float => "z.number()".into(), + 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().or(z.number())".into(), + cw_schema::NodeType::Binary => "z.string().base64()".into(), + + cw_schema::NodeType::Boxed { inner } => { + let node = &schema.definitions[inner]; + expand_node_name(schema, node) + } + cw_schema::NodeType::Optional { inner } => { + let inner = &schema.definitions[inner]; + format!("{}.nullable()", expand_node_name(schema, inner)).into() + } + + cw_schema::NodeType::Map { key, value, .. } => { + let key = expand_node_name(schema, &schema.definitions[key]); + let value = expand_node_name(schema, &schema.definitions[value]); + + format!("z.record({key}, {value})").into() + } + cw_schema::NodeType::Struct(..) => format!("{}Schema", node.name).into(), + cw_schema::NodeType::Tuple { ref items } => { + let items = items + .iter() + .map(|item| expand_node_name(schema, &schema.definitions[*item])) + .collect::>() + .join(", "); + + format!("z.tuple([{}])", items).into() + } + cw_schema::NodeType::Enum { .. } => format!("{}Schema", node.name).into(), + + cw_schema::NodeType::Decimal { .. } => "z.string()".into(), + cw_schema::NodeType::Address => "z.string()".into(), + cw_schema::NodeType::Checksum => { + // ToDo: Use actual checksum types + "z.string()".into() + } + cw_schema::NodeType::HexBinary => { + // ToDo: Actually use a binary decoding hex type + "z.string()".into() + } + cw_schema::NodeType::Timestamp => { + // ToDo: Replace with better type + "z.string()".into() + } + cw_schema::NodeType::Unit => "z.void()".into(), + } +} + +fn prepare_docs(desc: Option<&str>) -> Cow<'_, [Cow<'_, str>]> { + desc.map(|desc| desc.lines().map(Into::into).collect()) + .unwrap_or(Cow::Borrowed(&[])) +} + +pub fn process_node( + output: &mut O, + schema: &cw_schema::SchemaV1, + node: &cw_schema::Node, + add_imports: bool, +) -> io::Result<()> +where + O: io::Write, +{ + match node.value { + cw_schema::NodeType::Struct(ref sty) => { + let structt = StructTemplate { + name: node.name.clone(), + docs: prepare_docs(node.description.as_deref()), + ty: match sty { + cw_schema::StructType::Unit => TypeTemplate::Unit, + cw_schema::StructType::Named { ref properties } => TypeTemplate::Named { + fields: properties + .iter() + .map(|(name, prop)| FieldTemplate { + name: Cow::Borrowed(name), + docs: prepare_docs(prop.description.as_deref()), + ty: expand_node_name(schema, &schema.definitions[prop.value]), + }) + .collect(), + }, + cw_schema::StructType::Tuple { ref items } => TypeTemplate::Tuple( + items + .iter() + .map(|item| expand_node_name(schema, &schema.definitions[*item])) + .collect(), + ), + }, + add_imports, + }; + + writeln!(output, "{structt}")?; + } + cw_schema::NodeType::Enum { ref cases, .. } => { + let enumm = EnumTemplate { + name: node.name.clone(), + docs: prepare_docs(node.description.as_deref()), + variants: cases + .iter() + .map(|(name, case)| EnumVariantTemplate { + name: name.clone(), + docs: prepare_docs(case.description.as_deref()), + ty: match case.value { + cw_schema::EnumValue::Unit => TypeTemplate::Unit, + cw_schema::EnumValue::Tuple { ref items } => { + let items = items + .iter() + .map(|item| { + expand_node_name(schema, &schema.definitions[*item]) + }) + .collect(); + + TypeTemplate::Tuple(items) + } + cw_schema::EnumValue::Named { ref properties, .. } => { + TypeTemplate::Named { + fields: properties + .iter() + .map(|(name, prop)| FieldTemplate { + name: Cow::Borrowed(name), + docs: prepare_docs(prop.description.as_deref()), + ty: expand_node_name( + schema, + &schema.definitions[prop.value], + ), + }) + .collect(), + } + } + }, + }) + .collect(), + add_imports, + }; + + writeln!(output, "{enumm}")?; + } + _ => (), + } + + Ok(()) +} diff --git a/packages/cw-schema-codegen/src/typescript/template.rs b/packages/cw-schema-codegen/src/typescript/template.rs new file mode 100644 index 0000000000..89af73e396 --- /dev/null +++ b/packages/cw-schema-codegen/src/typescript/template.rs @@ -0,0 +1,43 @@ +use askama::Template; +use std::borrow::Cow; + +#[derive(Clone)] +pub struct EnumVariantTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: TypeTemplate<'a>, +} + +#[derive(Template)] +#[template(escape = "none", path = "typescript/enum.tpl.ts")] +pub struct EnumTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub variants: Cow<'a, [EnumVariantTemplate<'a>]>, + pub add_imports: bool, +} + +#[derive(Clone)] +pub struct FieldTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: Cow<'a, str>, +} + +#[derive(Clone)] +pub enum TypeTemplate<'a> { + Unit, + Tuple(Cow<'a, [Cow<'a, str>]>), + Named { + fields: Cow<'a, [FieldTemplate<'a>]>, + }, +} + +#[derive(Template)] +#[template(escape = "none", path = "typescript/struct.tpl.ts")] +pub struct StructTemplate<'a> { + pub name: Cow<'a, str>, + pub docs: Cow<'a, [Cow<'a, str>]>, + pub ty: TypeTemplate<'a>, + pub add_imports: bool, +} diff --git a/packages/cw-schema-codegen/templates/go/enum.tpl.go b/packages/cw-schema-codegen/templates/go/enum.tpl.go new file mode 100644 index 0000000000..eba8229d8a --- /dev/null +++ b/packages/cw-schema-codegen/templates/go/enum.tpl.go @@ -0,0 +1,106 @@ +// This code is @generated by cw-schema-codegen. Do not modify this manually. + +{% if add_package %} +import ( + _ "github.com/cosmos/cosmos-sdk/types/address" +) +{% endif %} +{% if has_unit_variants %} +import ( + "encoding/json" + "fmt" +) +{% endif %} + +{% for variant in variants %} +{% match variant.ty %} +{% when TypeTemplate::Unit %} +type {{ name }}{{ variant.name }} struct{} +{% when TypeTemplate::Tuple(types) %} +type {{ name }}{{ variant.name }} {% if types.len() > 1 %}[]interface{}{% else %}{{ types[0] }}{% endif %} +{% when TypeTemplate::Named { fields } %} +type {{ name }}{{ variant.name }} struct { + {% for field in fields %} + {% for doc in docs %} + // {{ doc }} + {% endfor %} + {{ field.name }} {{ field.ty }} `json:"{{ field.rename }}"` + {% endfor %} +} +{% endmatch %} +{% endfor %} + +{% for doc in docs %} + // {{ doc }} +{% endfor %} +type {{ name }} struct { +{% for variant in variants %} +{% for doc in docs %} + // {{ doc }} +{% endfor %} + {{ variant.name }} *{{ name }}{{ variant.name }} `json:"{{ variant.rename }},omitempty"` +{% endfor %} +} +{% if has_unit_variants %} +// UnmarshalJSON implements the json.Unmarshaler interface for {{ name }}. +// {{ name }} contains unit variants, which are represented as strings in the JSON. +func (v *{{ name }}) UnmarshalJSON(data []byte) error { + var raw struct { + {% for variant in variants %} + {{ variant.name }} *{{ name }}{{ variant.name }} `json:"{{ variant.rename }},omitempty"` + {% endfor %} + } + + // try to parse directly first + if err := json.Unmarshal(data, &raw); err != nil { + // try to parse as string + var s string + if err2 := json.Unmarshal(data, &s); err2 != nil { + return fmt.Errorf("failed to unmarshal {{ name }}: %w, %w", err, err2) + } + + // check if it's one of the unit variants + switch s { + {% for variant in variants %} + {% if variant.ty.is_unit() %} + case "{{ variant.rename }}": + raw.{{ variant.name }} = &{{ name }}{{ variant.name }}{} + {% endif %} + {% endfor %} + default: + return fmt.Errorf("failed to unmarshal {{ name }}: %w, no matching variant for string %s", err, s) + } + } + + // Assign the values to the receiver + *(*{{ name }})(v) = {{ name }}{ + {% for variant in variants %} + {{ variant.name }}: raw.{{ variant.name }}, + {% endfor %} + } + + return nil +} + + +func (v {{ name }}) MarshalJSON() ([]byte, error) { + switch { + {% for variant in variants %} + {% if variant.ty.is_unit() %} + case v.{{ variant.name }} != nil: + return []byte(`"{{ variant.rename }}"`), nil + {% endif %} + {% endfor %} + default: + return json.Marshal(struct { + {% for variant in variants %} + {{ variant.name }} *{{ name }}{{ variant.name }} `json:"{{ variant.rename }},omitempty"` + {% endfor %} + }{ + {% for variant in variants %} + {{ variant.name }}: v.{{ variant.name }}, + {% endfor %} + }) + } +} +{% endif %} diff --git a/packages/cw-schema-codegen/templates/go/struct.tpl.go b/packages/cw-schema-codegen/templates/go/struct.tpl.go new file mode 100644 index 0000000000..ea8ad79b8a --- /dev/null +++ b/packages/cw-schema-codegen/templates/go/struct.tpl.go @@ -0,0 +1,26 @@ +// This code is @generated by cw-schema-codegen. Do not modify this manually. + +{% if add_package %} +import ( + _ "github.com/cosmos/cosmos-sdk/types" +) +{% endif %} + +{% for doc in docs %} + // {{ doc }} +{% endfor %} +{% match ty %} +{% when TypeTemplate::Unit %} +type {{ name }} struct{} +{% when TypeTemplate::Tuple with (types) %} +type {{ name }} []interface{} /* todo: replace with true tuples if i can think of it */ +{% when TypeTemplate::Named with { fields } %} +type {{ name }} struct { +{% for field in fields %} +{% for doc in docs %} + // {{ doc }} +{% endfor %} + {{ field.name }} *{{ field.ty }} `json:"{{ field.rename }}"` +{% endfor %} +} +{% endmatch %} diff --git a/packages/cw-schema-codegen/templates/python/enum.tpl.py b/packages/cw-schema-codegen/templates/python/enum.tpl.py new file mode 100644 index 0000000000..05075e80c8 --- /dev/null +++ b/packages/cw-schema-codegen/templates/python/enum.tpl.py @@ -0,0 +1,41 @@ +# This code is @generated by cw-schema-codegen. Do not modify this manually. + +import typing +import decimal +from pydantic import BaseModel, RootModel + +class {{ name }}(RootModel): + """{% for doc in docs %} + {{ doc }} + {% endfor %}""" + +{% for variant in variants %} +{% match variant.ty %} +{% when TypeTemplate::Unit %} + class {{ variant.name }}(RootModel): + """{% for doc in variant.docs %} + {{ doc }} + {% endfor %}""" + root: typing.Literal['{{ variant.name }}'] +{% when TypeTemplate::Tuple with (types) %} + class {{ variant.name }}(BaseModel): + """{% for doc in variant.docs %} + {{ doc }} + {% endfor %}""" + {{ variant.name }}: {% if types.len() == 1 %}typing.Union[{{ types[0] }}, typing.Tuple[{{ types[0] }}]]{% else %}typing.Tuple[{{ types|join(", ") }}]{% endif %} +{% when TypeTemplate::Named with { fields } %} + class {{ variant.name }}(BaseModel): + class __Inner(BaseModel): + """{% for doc in variant.docs %} + {{ doc }} + {% endfor %}""" + {% for field in fields %} + {{ field.name }}: {{ field.ty }} + """{% for doc in field.docs %} + {{ doc }} + {% endfor %}""" + {% endfor %} + {{ variant.name }}: __Inner +{% endmatch %} +{% endfor %} + root: typing.Union[ {% for variant in variants %} {{ variant.name }}, {% endfor %} ] diff --git a/packages/cw-schema-codegen/templates/python/struct.tpl.py b/packages/cw-schema-codegen/templates/python/struct.tpl.py new file mode 100644 index 0000000000..1825fb321d --- /dev/null +++ b/packages/cw-schema-codegen/templates/python/struct.tpl.py @@ -0,0 +1,32 @@ +# This code is @generated by cw-schema-codegen. Do not modify this manually. + +import typing +import decimal +from pydantic import BaseModel, RootModel, Base64Bytes + + +{% match ty %} +{% when TypeTemplate::Unit %} +class {{ name }}(RootModel): + """{% for doc in docs %} + {{ doc }} + {% endfor %}""" + root: None +{% when TypeTemplate::Tuple with (types) %} +class {{ name }}(RootModel): + """{% for doc in docs %} + {{ doc }} + {% endfor %}""" + root: typing.Tuple[{{ types|join(", ") }}] +{% when TypeTemplate::Named with { fields } %} +class {{ name }}(BaseModel): + """{% for doc in docs %} + {{ doc }} + {% endfor %}""" + {% for field in fields %} + {{ field.name }}: {{ field.ty }} + """{% for doc in field.docs %} + # {{ doc }} + {% endfor %}""" + {% endfor %} +{% endmatch %} diff --git a/packages/cw-schema-codegen/templates/rust/enum.tpl.rs b/packages/cw-schema-codegen/templates/rust/enum.tpl.rs new file mode 100644 index 0000000000..bf4c321dc9 --- /dev/null +++ b/packages/cw-schema-codegen/templates/rust/enum.tpl.rs @@ -0,0 +1,43 @@ +// This code is @generated by cw-schema-codegen. Do not modify this manually. + +{% if add_allow %} +#![allow(non_camel_case_types)] +{% endif %} + +{% for doc in docs %} + #[doc = "{{ doc }}"] +{% endfor %} + +#[cosmwasm_schema::cw_serde] +pub enum {{ name }} { +{% for variant in variants %} +{% for doc in variant.docs %} + #[doc = "{{ doc }}"] +{% endfor %} + +{% match variant.serde_rename %} +{% when Some with (rename) %} + #[serde(rename = "{{ rename }}")] +{% when None %} +{% endmatch %} + + {{ variant.name }} +{% match variant.ty %} +{% when TypeTemplate::Unit %} +{% when TypeTemplate::Tuple with (types) %} + ( + {{ types|join(", ") }} + ) +{% when TypeTemplate::Named with { fields } %} + { + {% for field in fields %} + {% for doc in field.docs %} + #[doc = "{{ doc }}"] + {% endfor %} + {{ field.name }}: {{ field.ty }}, + {% endfor %} + } +{% endmatch %} + , +{% endfor %} +} \ No newline at end of file diff --git a/packages/cw-schema-codegen/templates/rust/struct.tpl.rs b/packages/cw-schema-codegen/templates/rust/struct.tpl.rs new file mode 100644 index 0000000000..2de740ffbd --- /dev/null +++ b/packages/cw-schema-codegen/templates/rust/struct.tpl.rs @@ -0,0 +1,35 @@ +// This code is @generated by cw-schema-codegen. Do not modify this manually. + +{% if add_allow %} +#![allow(non_camel_case_types)] +{% endif %} + +{% for doc in docs %} +#[doc = "{{ doc }}"] +{% endfor %} + +#[cosmwasm_schema::cw_serde] +pub struct {{ name }} + +{% match ty %} +{% when TypeTemplate::Unit %} +; +{% when TypeTemplate::Tuple with (types) %} +( + {{ types|join(", ") }} +); +{% when TypeTemplate::Named with { fields } %} +{ +{% for field in fields %} +{% for doc in field.docs %} + #[doc = "{{ doc }}"] +{% endfor %} + +{% if field.defaulting %} + #[serde(default)] +{% endif %} + + {{ field.name }}: {{ field.ty }}, +{% endfor %} +} +{% endmatch %} diff --git a/packages/cw-schema-codegen/templates/typescript/enum.tpl.ts b/packages/cw-schema-codegen/templates/typescript/enum.tpl.ts new file mode 100644 index 0000000000..6cd09b8198 --- /dev/null +++ b/packages/cw-schema-codegen/templates/typescript/enum.tpl.ts @@ -0,0 +1,55 @@ +// This code is @generated by cw-schema-codegen. Do not modify this manually. + +{% if add_imports %} +import { z } from 'zod'; +{% endif %} + +/** +{% for doc in docs %} + * {{ doc }} +{% endfor %} + */ + +const {{ name }}Schema = z.union([ +{% for variant in variants %} + /** + {% for doc in variant.docs %} + * {{ doc }} + {% endfor %} + */ + +{% match variant.ty %} +{% when TypeTemplate::Unit %} + z.object({ "{{ variant.name }}": z.null() }).or(z.literal("{{ variant.name }}")), +{% when TypeTemplate::Tuple with (types) %} + z.object({ + "{{ variant.name }}": z.tuple([{{ types|join(", ") }}]) + {% if types.len() == 1 %} + .or({{ types[0] }}) + {% endif %} + }) + + , +{% when TypeTemplate::Named with { fields } %} + z.object({ "{{ variant.name }}": z.object({ +{% for field in fields %} + /** + {% for doc in field.docs %} + * {{ doc }} + {% endfor %} + */ + + {{ field.name }}: {{ field.ty }}, +{% endfor %} +}) }), +{% endmatch %} +{% endfor %} + +{% if variants.len() == 0 %} +never; +{% endif %} +]); + +type {{ name }} = z.infer; + +export { {{ name }}, {{ name }}Schema }; diff --git a/packages/cw-schema-codegen/templates/typescript/struct.tpl.ts b/packages/cw-schema-codegen/templates/typescript/struct.tpl.ts new file mode 100644 index 0000000000..4f17725dc0 --- /dev/null +++ b/packages/cw-schema-codegen/templates/typescript/struct.tpl.ts @@ -0,0 +1,39 @@ +// This code is @generated by cw-schema-codegen. Do not modify this manually. + +{% if add_imports %} +import { z } from 'zod'; +{% endif %} + +/** +{% for doc in docs %} + * {{ doc }} +{% endfor %} + */ + +const {{ name }}Schema = +{% match ty %} +{% when TypeTemplate::Unit %} + z.null() +{% when TypeTemplate::Tuple with (types) %} + z.tuple([{{ types|join(", ") }}]) + {% if types.len() == 1 %} + .or({{ types[0] }}) + {% endif %} +{% when TypeTemplate::Named with { fields } %} + z.object({ +{% for field in fields %} + /** + {% for doc in field.docs %} + * {{ doc }} + {% endfor %} + */ + + {{ field.name }}: {{ field.ty }}, +{% endfor %} +}) +{% endmatch %} +; + +type {{ name }} = z.infer; + +export { {{ name }}, {{ name }}Schema }; diff --git a/packages/cw-schema-codegen/tests/go-e2e/.gitignore b/packages/cw-schema-codegen/tests/go-e2e/.gitignore new file mode 100644 index 0000000000..ea1bc79da0 --- /dev/null +++ b/packages/cw-schema-codegen/tests/go-e2e/.gitignore @@ -0,0 +1 @@ +gen.go \ No newline at end of file diff --git a/packages/cw-schema-codegen/tests/go-e2e/go.mod b/packages/cw-schema-codegen/tests/go-e2e/go.mod new file mode 100644 index 0000000000..7ada1028e0 --- /dev/null +++ b/packages/cw-schema-codegen/tests/go-e2e/go.mod @@ -0,0 +1,93 @@ +module cosmwasm.com/cosmwasm-codegen/e2e + +go 1.23 + +require github.com/cosmos/cosmos-sdk v0.50.11 + +require ( + cosmossdk.io/api v0.7.6 // indirect + cosmossdk.io/collections v0.4.0 // indirect + cosmossdk.io/core v0.11.0 // indirect + cosmossdk.io/depinject v1.1.0 // indirect + cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/log v1.4.1 // indirect + cosmossdk.io/math v1.4.0 // indirect + cosmossdk.io/store v1.1.1 // indirect + cosmossdk.io/x/tx v0.13.7 // indirect + github.com/DataDog/zstd v1.5.5 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cockroachdb/errors v1.11.3 // indirect + github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v1.1.2 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/cometbft/cometbft v0.38.12 // indirect + github.com/cometbft/cometbft-db v0.11.0 // indirect + github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-db v1.1.0 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect + github.com/cosmos/gogoproto v1.7.0 // indirect + github.com/cosmos/ics23/go v0.11.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/dgraph-io/badger/v2 v2.2007.4 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect + github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/glog v1.2.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-metrics v0.5.3 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/linxGnu/grocksdb v1.8.14 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect + github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.20.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/rs/zerolog v1.33.0 // indirect + github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/spf13/cast v1.7.0 // indirect + github.com/spf13/cobra v1.8.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + go.etcd.io/bbolt v1.3.10 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/grpc v1.67.1 // indirect + google.golang.org/protobuf v1.35.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) diff --git a/packages/cw-schema-codegen/tests/go-e2e/go.sum b/packages/cw-schema-codegen/tests/go-e2e/go.sum new file mode 100644 index 0000000000..290fe98b71 --- /dev/null +++ b/packages/cw-schema-codegen/tests/go-e2e/go.sum @@ -0,0 +1,407 @@ +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= +cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= +cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= +cosmossdk.io/core v0.11.0/go.mod h1:LaTtayWBSoacF5xNzoF8tmLhehqlA9z1SWiPuNC6X1w= +cosmossdk.io/depinject v1.1.0 h1:wLan7LG35VM7Yo6ov0jId3RHWCGRhe8E8bsuARorl5E= +cosmossdk.io/depinject v1.1.0/go.mod h1:kkI5H9jCGHeKeYWXTqYdruogYrEeWvBQCw1Pj4/eCFI= +cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= +cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= +cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM= +cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU= +cosmossdk.io/math v1.4.0 h1:XbgExXFnXmF/CccPPEto40gOO7FpWu9yWNAZPN3nkNQ= +cosmossdk.io/math v1.4.0/go.mod h1:O5PkD4apz2jZs4zqFdTr16e1dcaQCc5z6lkEnrrppuk= +cosmossdk.io/store v1.1.1 h1:NA3PioJtWDVU7cHHeyvdva5J/ggyLDkyH0hGHl2804Y= +cosmossdk.io/store v1.1.1/go.mod h1:8DwVTz83/2PSI366FERGbWSH7hL6sB7HbYp8bqksNwM= +cosmossdk.io/x/tx v0.13.7 h1:8WSk6B/OHJLYjiZeMKhq7DK7lHDMyK0UfDbBMxVmeOI= +cosmossdk.io/x/tx v0.13.7/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= +github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.2 h1:CUh2IPtR4swHlEj48Rhfzw6l/d0qA31fItcIszQVIsA= +github.com/cockroachdb/pebble v1.1.2/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/cometbft/cometbft v0.38.12 h1:OWsLZN2KcSSFe8bet9xCn07VwhBnavPea3VyPnNq1bg= +github.com/cometbft/cometbft v0.38.12/go.mod h1:GPHp3/pehPqgX1930HmK1BpBLZPxB75v/dZg8Viwy+o= +github.com/cometbft/cometbft-db v0.11.0 h1:M3Lscmpogx5NTbb1EGyGDaFRdsoLWrUWimFEyf7jej8= +github.com/cometbft/cometbft-db v0.11.0/go.mod h1:GDPJAC/iFHNjmZZPN8V8C1yr/eyityhi2W1hz2MGKSc= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= +github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/cosmos-db v1.1.0 h1:KLHNVQ73h7vawXTpj9UJ7ZR2IXv51tsEHkQJJ9EBDzI= +github.com/cosmos/cosmos-db v1.1.0/go.mod h1:t7c4A6cfGdpUwwVxrQ0gQLeRQqGUBJu0yvE4F/26REg= +github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= +github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= +github.com/cosmos/cosmos-sdk v0.50.11 h1:LxR1aAc8kixdrs3itO+3a44sFoc+vjxVAOyPFx22yjk= +github.com/cosmos/cosmos-sdk v0.50.11/go.mod h1:gt14Meok2IDCjbDtjwkbUcgVNEpUBDN/4hg9cCUtLgw= +github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= +github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= +github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= +github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= +github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= +github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= +github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= +github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-metrics v0.5.3 h1:M5uADWMOGCTUNU1YuC4hfknOeHNaX54LDm4oYSucoNE= +github.com/hashicorp/go-metrics v0.5.3/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/linxGnu/grocksdb v1.8.14 h1:HTgyYalNwBSG/1qCQUIott44wU5b2Y9Kr3z7SK5OfGQ= +github.com/linxGnu/grocksdb v1.8.14/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 h1:jik8PHtAIsPlCRJjJzl4udgEf7hawInF9texMeO2jrU= +github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.20.1 h1:IMJXHOD6eARkQpxo8KkhgEVFlBNm+nkrFUyGlIu7Na8= +github.com/prometheus/client_golang v1.20.1/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= +github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= +github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= +go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/packages/cw-schema-codegen/tests/go-e2e/main.go b/packages/cw-schema-codegen/tests/go-e2e/main.go new file mode 100644 index 0000000000..6f6e1ff0f8 --- /dev/null +++ b/packages/cw-schema-codegen/tests/go-e2e/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "os" +) + +func main() { + var buffer bytes.Buffer + + _, err := io.Copy(&buffer, os.Stdin) + if err != nil { + panic(err) + } + + data := buffer.Bytes() + + var out *TestType + if err := json.Unmarshal(data, &out); err != nil { + panic(err) + } + + fmt.Fprintln(os.Stderr, out) + + marshalled, err := json.Marshal(out) + if err != nil { + panic(err) + } + + os.Stdout.Write(marshalled) +} diff --git a/packages/cw-schema-codegen/tests/go.rs b/packages/cw-schema-codegen/tests/go.rs new file mode 100644 index 0000000000..6040f6d7ad --- /dev/null +++ b/packages/cw-schema-codegen/tests/go.rs @@ -0,0 +1,38 @@ +use std::{fs::File, io::Write, process::Command}; + +use crate::utils::TestCase; + +mod utils; + +#[test] +#[ignore] // because it requires Go to be installed, CI will still run it +fn e2e() { + let e2e_dir = format!("{}/tests/go-e2e", env!("CARGO_MANIFEST_DIR")); + let gen_file_path = format!("{e2e_dir}/gen.go"); + + // make sure the dependencies are installed + let install_status = Command::new("go") + .args(["get"]) + .current_dir(&e2e_dir) + .status() + .unwrap(); + + assert!(install_status.success()); + + utils::run_e2e( + |buf, schema, node| cw_schema_codegen::go::process_node(buf, schema, node, true), + |TestCase { code, type_name }| { + let mut gen_file = File::create(&gen_file_path).unwrap(); + gen_file.write_all(b"package main\n").unwrap(); + gen_file.write_all(code.as_bytes()).unwrap(); + gen_file + .write_all(format!("type TestType = {type_name}").as_bytes()) + .unwrap(); + + let mut cmd = Command::new("go"); + cmd.args(["run", "main.go", "gen.go"]).current_dir(&e2e_dir); + + cmd + }, + ); +} diff --git a/packages/cw-schema-codegen/tests/python_tpl.rs b/packages/cw-schema-codegen/tests/python_tpl.rs new file mode 100644 index 0000000000..6b10f91a50 --- /dev/null +++ b/packages/cw-schema-codegen/tests/python_tpl.rs @@ -0,0 +1,240 @@ +use cw_schema::Schemaifier; +use serde::{Deserialize, Serialize}; +use std::{ + io::{Seek, Write}, + process::Command, +}; + +use crate::utils::TestCase; + +mod utils; + +/// This is a struct level documentation for enum type +#[derive(Schemaifier, Serialize, Deserialize, PartialEq, Debug)] +pub enum SomeEnum { + /// Field1 docs + Field1, + + /// Field2 docs + Field2(u32, u32), + + /// Field3 docs + Field3 { + /// `a` field docs + a: String, + + /// `b` field docs + b: u32, + }, + + Field4(u32), +} + +/// This is a struct level documentation for unit struct +#[derive(Schemaifier, Serialize, Deserialize, PartialEq, Debug)] +pub struct UnitStructure; + +/// This is a struct level documentation for tuple +#[derive(Schemaifier, Serialize, Deserialize, PartialEq, Debug)] +pub struct TupleStructure(u32, String, u128); + +/// This is a struct level documentation for named structure +#[derive(Schemaifier, Serialize, Deserialize, PartialEq, Debug)] +pub struct NamedStructure { + /// `a` field docs + a: String, + + /// `b` field docs + b: u8, + + /// `c` field docs + c: SomeEnum, +} + +#[derive(Schemaifier, Serialize, Deserialize, PartialEq, Debug)] +pub struct AllSimpleTypesAndDocs { + array_field: Vec, + float_field: f32, + double_field: f64, + bool_field: bool, + string_field: String, + int_field: i64, + bytes_field: cosmwasm_std::Binary, + opt_field: Option, + byte_field: u8, + decimal_field: cosmwasm_std::Decimal, + address_field: cosmwasm_std::Addr, + checksum_field: cosmwasm_std::Checksum, + hexbinary_field: cosmwasm_std::HexBinary, + timestamp_field: cosmwasm_std::Timestamp, + unit_field: (), +} + +#[test] +fn simple_enum() { + // generate the schemas for each of the above types + let schemas = [ + cw_schema::schema_of::(), + cw_schema::schema_of::(), + cw_schema::schema_of::(), + cw_schema::schema_of::(), + ]; + + // run the codegen to typescript + for schema in schemas { + let cw_schema::Schema::V1(schema) = schema else { + panic!(); + }; + + let output = schema + .definitions + .iter() + .map(|node| { + let mut buf = Vec::new(); + cw_schema_codegen::python::process_node(&mut buf, &schema, node).unwrap(); + String::from_utf8(buf).unwrap() + }) + .collect::(); + + insta::assert_snapshot!(output); + } +} + +macro_rules! validator { + ($ty:ty, $example:expr) => {{ + ( + ::std::any::type_name::<$ty>().replace("::", "_"), + cw_schema::schema_of::<$ty>(), + serde_json::to_string(&$example).unwrap(), + { + let a: Box = Box::new(|output| { + let result = serde_json::from_str::<$ty>(output).unwrap(); + assert_eq!(result, $example); + }); + a + }, + ) + }}; +} + +#[test] +#[ignore] // because it requires Python to be installed, CI will still run it +fn assert_validity() { + let schemas = [ + validator!(SomeEnum, SomeEnum::Field1), + validator!(SomeEnum, SomeEnum::Field2(10, 23)), + validator!( + SomeEnum, + SomeEnum::Field3 { + a: "sdf".to_string(), + b: 12, + } + ), + validator!(SomeEnum, SomeEnum::Field4(42)), + validator!(UnitStructure, UnitStructure {}), + validator!(TupleStructure, TupleStructure(10, "aasdf".to_string(), 2)), + validator!( + NamedStructure, + NamedStructure { + a: "awer".to_string(), + b: 4, + c: SomeEnum::Field1, + } + ), + validator!( + AllSimpleTypesAndDocs, + AllSimpleTypesAndDocs { + array_field: vec!["abc".to_string(), "def".to_string()], + float_field: 10.2, + double_field: 10.232323, + bool_field: true, + string_field: "sdfsdf".to_string(), + int_field: -10, + bytes_field: cosmwasm_std::Binary::new(vec![0x1, 0x2, 0x3]), + opt_field: Some("sdfsdfwer".to_string()), + byte_field: 9, + decimal_field: cosmwasm_std::Decimal::one(), + address_field: cosmwasm_std::Addr::unchecked("some_address"), + checksum_field: cosmwasm_std::Checksum::generate(&[0x10]), + hexbinary_field: cosmwasm_std::HexBinary::from_hex("FAFAFA").unwrap(), + timestamp_field: cosmwasm_std::Timestamp::from_seconds(100), + unit_field: (), + } + ), + ]; + + for (type_name, schema, example, validator) in schemas { + let cw_schema::Schema::V1(schema) = schema else { + unreachable!(); + }; + + let schema_output = schema + .definitions + .iter() + .rev() + .map(|node| { + let mut buf = Vec::new(); + cw_schema_codegen::python::process_node(&mut buf, &schema, node).unwrap(); + String::from_utf8(buf).unwrap() + }) + .collect::(); + + let mut file = tempfile::NamedTempFile::with_suffix(".py").unwrap(); + file.write_all(schema_output.as_bytes()).unwrap(); + file.write_all( + format!( + "import sys; print({type_name}.model_validate_json('{example}').model_dump_json())" + ) + .as_bytes(), + ) + .unwrap(); + file.flush().unwrap(); + + let output = std::process::Command::new("python3") + .arg(file.path()) + .output() + .unwrap(); + + assert!( + output.status.success(), + "stdout: {stdout}, stderr: {stderr}\n\n schema:\n {schema_output}", + stdout = String::from_utf8_lossy(&output.stdout), + stderr = String::from_utf8_lossy(&output.stderr), + ); + + validator(&String::from_utf8_lossy(&output.stdout)) + } +} + +#[test] +#[ignore] // because it requires Python to be installed, CI will still run it +fn e2e() { + // temp file for the generated Python code + let mut file = tempfile::NamedTempFile::with_suffix(".py").unwrap(); + + utils::run_e2e( + |buf, schema, node| cw_schema_codegen::python::process_node(buf, schema, node), + |TestCase { code, type_name }| { + // clear the file and write from the start again + file.as_file().set_len(0).unwrap(); + file.as_file_mut() + .seek(std::io::SeekFrom::Start(0)) + .unwrap(); + + file.write_all(code.as_bytes()).unwrap(); + file.write_all( + format!( + "import sys; print({type_name}.model_validate_json(sys.stdin.read()).model_dump_json())" + ) + .as_bytes(), + ) + .unwrap(); + file.flush().unwrap(); + + let mut cmd = Command::new("python3"); + cmd.arg(file.path()); + + cmd + }, + ); +} diff --git a/packages/cw-schema-codegen/tests/rust-e2e/Cargo.lock b/packages/cw-schema-codegen/tests/rust-e2e/Cargo.lock new file mode 100644 index 0000000000..ae2143f78a --- /dev/null +++ b/packages/cw-schema-codegen/tests/rust-e2e/Cargo.lock @@ -0,0 +1,510 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "cosmwasm-schema" +version = "3.0.1" +dependencies = [ + "cosmwasm-schema-derive", + "cw-schema", + "schemars 0.8.21", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "3.0.1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cw-schema" +version = "3.0.1" +dependencies = [ + "cw-schema-derive", + "indexmap", + "schemars 1.0.0-alpha.17", + "serde", + "serde_with", + "siphasher", + "typeid", +] + +[[package]] +name = "cw-schema-derive" +version = "3.0.1" +dependencies = [ + "heck", + "itertools", + "owo-colors", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "owo-colors" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56" +dependencies = [ + "supports-color 2.1.0", + "supports-color 3.0.2", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "rust-e2e" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "serde_json", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "schemars_derive 0.8.21", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.0.0-alpha.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ef2a6523400a2228db974a8ddc9e1d3deaa04f51bddd7832ef8d7e531bafcc" +dependencies = [ + "dyn-clone", + "ref-cast", + "schemars_derive 1.0.0-alpha.17", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "schemars_derive" +version = "1.0.0-alpha.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6d4e1945a3c9e58edaa708449b026519f7f4197185e1b5dbc689615c1ad724d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +dependencies = [ + "serde", + "serde_derive", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "supports-color" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" +dependencies = [ + "is-terminal", + "is_ci", +] + +[[package]] +name = "supports-color" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" +dependencies = [ + "is_ci", +] + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/packages/cw-schema-codegen/tests/rust-e2e/Cargo.toml b/packages/cw-schema-codegen/tests/rust-e2e/Cargo.toml new file mode 100644 index 0000000000..ef8cc5416c --- /dev/null +++ b/packages/cw-schema-codegen/tests/rust-e2e/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rust-e2e" +version = "0.1.0" +edition = "2024" + +[dependencies] +cosmwasm-schema = { version = "3.0.0", path = "../../../schema" } +serde_json = "1.0.137" diff --git a/packages/cw-schema-codegen/tests/rust-e2e/src/gen.rs b/packages/cw-schema-codegen/tests/rust-e2e/src/gen.rs new file mode 100644 index 0000000000..5e4e19b7ca --- /dev/null +++ b/packages/cw-schema-codegen/tests/rust-e2e/src/gen.rs @@ -0,0 +1,71 @@ +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +#![allow(non_camel_case_types)] + + + + +#[cosmwasm_schema::cw_serde] +pub struct rust_utils_Foo + + +{ + + + + + + foo_field_10: ::alloc::collections::BTreeMap, + + + + + + foo_field_11: (u32, String), + + + + + + foo_field_2: bool, + + + + + + foo_field_3: String, + + + + + + foo_field_4: i32, + + + + + + foo_field_5: u8, + + + + + + foo_field_6: Vec, + + + + + + foo_field_7: ::core::option::Option, + + + + + + foo_field_9: ::alloc::boxed::Box, + +} + +pub type TestType = rust_utils_Foo; \ No newline at end of file diff --git a/packages/cw-schema-codegen/tests/rust-e2e/src/main.rs b/packages/cw-schema-codegen/tests/rust-e2e/src/main.rs new file mode 100644 index 0000000000..7fa7aecc37 --- /dev/null +++ b/packages/cw-schema-codegen/tests/rust-e2e/src/main.rs @@ -0,0 +1,8 @@ +extern crate alloc; + +mod r#gen; + +fn main() { + let value: r#gen::TestType = serde_json::from_reader(std::io::stdin()).unwrap(); + serde_json::to_writer(std::io::stdout(), &value).unwrap(); +} diff --git a/packages/cw-schema-codegen/tests/rust.rs b/packages/cw-schema-codegen/tests/rust.rs new file mode 100644 index 0000000000..f232ab704a --- /dev/null +++ b/packages/cw-schema-codegen/tests/rust.rs @@ -0,0 +1,27 @@ +use std::{fs::File, io::Write, process::Command}; + +use crate::utils::TestCase; + +mod utils; + +#[test] +fn e2e() { + let e2e_dir = format!("{}/tests/rust-e2e", env!("CARGO_MANIFEST_DIR")); + let gen_file_path = format!("{e2e_dir}/src/gen.rs"); + + utils::run_e2e( + |buf, schema, node| cw_schema_codegen::rust::process_node(buf, schema, node, true), + |TestCase { code, type_name }| { + let mut gen_file = File::create(&gen_file_path).unwrap(); + gen_file.write_all(code.as_bytes()).unwrap(); + gen_file + .write_all(format!("pub type TestType = {type_name};").as_bytes()) + .unwrap(); + + let mut cmd = Command::new("cargo"); + cmd.args(["run"]).current_dir(&e2e_dir); + + cmd + }, + ); +} diff --git a/packages/cw-schema-codegen/tests/rust_tpl.rs b/packages/cw-schema-codegen/tests/rust_tpl.rs new file mode 100644 index 0000000000..26b485e994 --- /dev/null +++ b/packages/cw-schema-codegen/tests/rust_tpl.rs @@ -0,0 +1,142 @@ +use askama::Template; +use cw_schema_codegen::rust::template::{ + EnumTemplate, EnumVariantTemplate, FieldTemplate, StructTemplate, TypeTemplate, +}; +use std::borrow::Cow; + +#[test] +fn simple_enum() { + let tpl = EnumTemplate { + add_allow: true, + name: Cow::Borrowed("Simple"), + docs: Cow::Borrowed(&[Cow::Borrowed("Simple enum")]), + variants: Cow::Borrowed(&[ + EnumVariantTemplate { + name: Cow::Borrowed("One"), + docs: Cow::Borrowed(&[Cow::Borrowed("One variant")]), + serde_rename: None, + ty: TypeTemplate::Unit, + }, + EnumVariantTemplate { + name: Cow::Borrowed("Two"), + docs: Cow::Borrowed(&[Cow::Borrowed("Two variant")]), + serde_rename: None, + ty: TypeTemplate::Unit, + }, + ]), + }; + + let rendered = tpl.render().unwrap(); + insta::assert_snapshot!(rendered); +} + +#[test] +fn complex_enum() { + let tpl = EnumTemplate { + add_allow: true, + name: Cow::Borrowed("Complex"), + docs: Cow::Borrowed(&[Cow::Borrowed("Complex enum")]), + variants: Cow::Borrowed(&[ + EnumVariantTemplate { + name: Cow::Borrowed("One"), + docs: Cow::Borrowed(&[Cow::Borrowed("One variant")]), + serde_rename: None, + ty: TypeTemplate::Tuple(Cow::Borrowed(&[Cow::Borrowed("u64")])), + }, + EnumVariantTemplate { + name: Cow::Borrowed("Two"), + docs: Cow::Borrowed(&[Cow::Borrowed("Two variant")]), + serde_rename: None, + ty: TypeTemplate::Named { + fields: Cow::Borrowed(&[ + FieldTemplate { + name: Cow::Borrowed("a"), + defaulting: false, + docs: Cow::Borrowed(&[Cow::Borrowed("Field a")]), + ty: Cow::Borrowed("u64"), + }, + FieldTemplate { + name: Cow::Borrowed("b"), + defaulting: true, + docs: Cow::Borrowed(&[Cow::Borrowed("Field b")]), + ty: Cow::Borrowed("String"), + }, + ]), + }, + }, + ]), + }; + + let rendered = tpl.render().unwrap(); + insta::assert_snapshot!(rendered); +} + +#[test] +fn empty_enum() { + let tpl = EnumTemplate { + add_allow: true, + name: Cow::Borrowed("Empty"), + docs: Cow::Borrowed(&[Cow::Borrowed("Empty enum")]), + variants: Cow::Borrowed(&[]), + }; + + let rendered = tpl.render().unwrap(); + insta::assert_snapshot!(rendered); +} + +#[test] +fn empty_struct() { + let tpl = StructTemplate { + add_allow: true, + name: Cow::Borrowed("Empty"), + docs: Cow::Borrowed(&[Cow::Borrowed("Empty struct")]), + ty: TypeTemplate::Unit, + }; + + let rendered = tpl.render().unwrap(); + insta::assert_snapshot!(rendered); +} + +#[test] +fn tuple_struct() { + let tpl = StructTemplate { + add_allow: true, + name: Cow::Borrowed("Tuple"), + docs: Cow::Borrowed(&[Cow::Borrowed("Tuple struct")]), + ty: TypeTemplate::Tuple(Cow::Borrowed(&[ + Cow::Borrowed("u64"), + Cow::Borrowed("String"), + ])), + }; + + let rendered = tpl.render().unwrap(); + insta::assert_snapshot!(rendered); +} + +#[test] +fn named_struct() { + let tpl = StructTemplate { + add_allow: true, + name: Cow::Borrowed("Named"), + docs: Cow::Borrowed(&[Cow::Borrowed("Named struct")]), + ty: TypeTemplate::Named { + fields: Cow::Borrowed(&[ + FieldTemplate { + name: Cow::Borrowed("a"), + defaulting: false, + docs: Cow::Borrowed(&[Cow::Borrowed("Field a")]), + ty: Cow::Borrowed("u64"), + }, + FieldTemplate { + name: Cow::Borrowed("b"), + defaulting: true, + docs: Cow::Borrowed(&[Cow::Borrowed("Field b")]), + ty: Cow::Borrowed("String"), + }, + ]), + }, + }; + + let rendered = tpl.render().unwrap(); + insta::assert_snapshot!(rendered); +} diff --git a/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum-2.snap b/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum-2.snap new file mode 100644 index 0000000000..3edc68969b --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum-2.snap @@ -0,0 +1,17 @@ +--- +source: packages/cw-schema-codegen/tests/python_tpl.rs +expression: output +--- +# This code is @generated by cw-schema-codegen. Do not modify this manually. + +import typing +import decimal +from pydantic import BaseModel, RootModel, Base64Bytes + + + +class python_tpl_UnitStructure(RootModel): + """ + This is a struct level documentation for unit struct + """ + root: None diff --git a/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum-3.snap b/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum-3.snap new file mode 100644 index 0000000000..d7a70375eb --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum-3.snap @@ -0,0 +1,17 @@ +--- +source: packages/cw-schema-codegen/tests/python_tpl.rs +expression: output +--- +# This code is @generated by cw-schema-codegen. Do not modify this manually. + +import typing +import decimal +from pydantic import BaseModel, RootModel, Base64Bytes + + + +class python_tpl_TupleStructure(RootModel): + """ + This is a struct level documentation for tuple + """ + root: typing.Tuple[int, str, int] diff --git a/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum-4.snap b/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum-4.snap new file mode 100644 index 0000000000..c23f8beda8 --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum-4.snap @@ -0,0 +1,88 @@ +--- +source: packages/cw-schema-codegen/tests/python_tpl.rs +expression: output +--- +# This code is @generated by cw-schema-codegen. Do not modify this manually. + +import typing +import decimal +from pydantic import BaseModel, RootModel, Base64Bytes + + + +class python_tpl_NamedStructure(BaseModel): + """ + This is a struct level documentation for named structure + """ + + a: str + """ + # `a` field docs + """ + + b: int + """ + # `b` field docs + """ + + c: python_tpl_SomeEnum + """ + # `c` field docs + """ + + +# This code is @generated by cw-schema-codegen. Do not modify this manually. + +import typing +import decimal +from pydantic import BaseModel, RootModel + +class python_tpl_SomeEnum(RootModel): + """ + This is a struct level documentation for enum type + """ + + + + class Field1(RootModel): + """ + Field1 docs + """ + root: typing.Literal['Field1'] + + + + class Field2(BaseModel): + """ + Field2 docs + """ + Field2: typing.Tuple[int, int] + + + + class Field3(BaseModel): + class __Inner(BaseModel): + """ + Field3 docs + """ + + a: str + """ + `a` field docs + """ + + b: int + """ + `b` field docs + """ + + Field3: __Inner + + + + class Field4(BaseModel): + """""" + Field4: typing.Union[int, typing.Tuple[int]] + + + root: typing.Union[ Field1, Field2, Field3, Field4, ] diff --git a/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum.snap b/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum.snap new file mode 100644 index 0000000000..4044a7f133 --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/python_tpl__simple_enum.snap @@ -0,0 +1,59 @@ +--- +source: packages/cw-schema-codegen/tests/python_tpl.rs +expression: output +--- +# This code is @generated by cw-schema-codegen. Do not modify this manually. + +import typing +import decimal +from pydantic import BaseModel, RootModel + +class python_tpl_SomeEnum(RootModel): + """ + This is a struct level documentation for enum type + """ + + + + class Field1(RootModel): + """ + Field1 docs + """ + root: typing.Literal['Field1'] + + + + class Field2(BaseModel): + """ + Field2 docs + """ + Field2: typing.Tuple[int, int] + + + + class Field3(BaseModel): + class __Inner(BaseModel): + """ + Field3 docs + """ + + a: str + """ + `a` field docs + """ + + b: int + """ + `b` field docs + """ + + Field3: __Inner + + + + class Field4(BaseModel): + """""" + Field4: typing.Union[int, typing.Tuple[int]] + + + root: typing.Union[ Field1, Field2, Field3, Field4, ] diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__complex_enum.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__complex_enum.snap new file mode 100644 index 0000000000..f6783ff706 --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__complex_enum.snap @@ -0,0 +1,58 @@ +--- +source: packages/cw-schema-codegen/tests/rust_tpl.rs +expression: rendered +--- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +#![allow(non_camel_case_types)] + + + + #[doc = "Complex enum"] + + +#[cosmwasm_schema::cw_serde] +pub enum Complex { + + + #[doc = "One variant"] + + + + + + One + + ( + u64 + ) + + , + + + #[doc = "Two variant"] + + + + + + Two + + { + + + #[doc = "Field a"] + + a: u64, + + + #[doc = "Field b"] + + b: String, + + } + + , + +} diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_enum.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_enum.snap new file mode 100644 index 0000000000..4428dead45 --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_enum.snap @@ -0,0 +1,18 @@ +--- +source: packages/cw-schema-codegen/tests/rust_tpl.rs +expression: rendered +--- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +#![allow(non_camel_case_types)] + + + + #[doc = "Empty enum"] + + +#[cosmwasm_schema::cw_serde] +pub enum Empty { + +} diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_struct.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_struct.snap new file mode 100644 index 0000000000..91b2745bba --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__empty_struct.snap @@ -0,0 +1,19 @@ +--- +source: packages/cw-schema-codegen/tests/rust_tpl.rs +expression: rendered +--- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +#![allow(non_camel_case_types)] + + + +#[doc = "Empty struct"] + + +#[cosmwasm_schema::cw_serde] +pub struct Empty + + +; diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__named_struct.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__named_struct.snap new file mode 100644 index 0000000000..9e5336637e --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__named_struct.snap @@ -0,0 +1,39 @@ +--- +source: packages/cw-schema-codegen/tests/rust_tpl.rs +expression: rendered +--- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +#![allow(non_camel_case_types)] + + + +#[doc = "Named struct"] + + +#[cosmwasm_schema::cw_serde] +pub struct Named + + +{ + + + #[doc = "Field a"] + + + + + a: u64, + + + #[doc = "Field b"] + + + + #[serde(default)] + + + b: String, + +} diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__simple_enum.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__simple_enum.snap new file mode 100644 index 0000000000..df4bc83f59 --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__simple_enum.snap @@ -0,0 +1,42 @@ +--- +source: packages/cw-schema-codegen/tests/rust_tpl.rs +expression: rendered +--- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +#![allow(non_camel_case_types)] + + + + #[doc = "Simple enum"] + + +#[cosmwasm_schema::cw_serde] +pub enum Simple { + + + #[doc = "One variant"] + + + + + + One + + + , + + + #[doc = "Two variant"] + + + + + + Two + + + , + +} diff --git a/packages/cw-schema-codegen/tests/snapshots/rust_tpl__tuple_struct.snap b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__tuple_struct.snap new file mode 100644 index 0000000000..ae0490cac4 --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/rust_tpl__tuple_struct.snap @@ -0,0 +1,21 @@ +--- +source: packages/cw-schema-codegen/tests/rust_tpl.rs +expression: rendered +--- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +#![allow(non_camel_case_types)] + + + +#[doc = "Tuple struct"] + + +#[cosmwasm_schema::cw_serde] +pub struct Tuple + + +( + u64, String +); 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 new file mode 100644 index 0000000000..b102e7798a --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-2.snap @@ -0,0 +1,24 @@ +--- +source: packages/cw-schema-codegen/tests/typescript.rs +expression: output +--- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +import { z } from 'zod'; + + +/** + + */ + +const typescript_utils_UwuSchema = + + z.tuple([z.string(), z.string().or(z.number())]) + + +; + +type typescript_utils_Uwu = z.infer; + +export { typescript_utils_Uwu, typescript_utils_UwuSchema }; 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 new file mode 100644 index 0000000000..13291d001a --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-3.snap @@ -0,0 +1,23 @@ +--- +source: packages/cw-schema-codegen/tests/typescript.rs +expression: output +--- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +import { z } from 'zod'; + + +/** + + */ + +const typescript_utils_ÒwóSchema = + + z.null() + +; + +type typescript_utils_Òwó = z.infer; + +export { typescript_utils_Òwó, typescript_utils_ÒwóSchema }; diff --git a/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-4.snap b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-4.snap new file mode 100644 index 0000000000..e1914b260c --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-4.snap @@ -0,0 +1,25 @@ +--- +source: packages/cw-schema-codegen/tests/typescript.rs +expression: output +--- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +import { z } from 'zod'; + + +/** + + */ + +const typescript_utils_EmptySchema = z.union([ + + + +never; + +]); + +type typescript_utils_Empty = z.infer; + +export { typescript_utils_Empty, typescript_utils_EmptySchema }; 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 new file mode 100644 index 0000000000..7fa79b34c3 --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap-5.snap @@ -0,0 +1,62 @@ +--- +source: packages/cw-schema-codegen/tests/typescript.rs +expression: output +--- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +import { z } from 'zod'; + + +/** + + */ + +const typescript_utils_HeheheSchema = z.union([ + + /** + + */ + + + z.object({ "A": z.null() }).or(z.literal("A")), + + + /** + + */ + + + z.object({ + "B": z.tuple([z.string().or(z.number())]) + + .or(z.string().or(z.number())) + + }) + + , + + + /** + + */ + + + z.object({ "C": z.object({ + + /** + + */ + + field: z.string(), + +}) }), + + + + +]); + +type typescript_utils_Hehehe = z.infer; + +export { typescript_utils_Hehehe, typescript_utils_HeheheSchema }; diff --git a/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap.snap b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap.snap new file mode 100644 index 0000000000..2d35248027 --- /dev/null +++ b/packages/cw-schema-codegen/tests/snapshots/typescript__codegen_snap.snap @@ -0,0 +1,37 @@ +--- +source: packages/cw-schema-codegen/tests/typescript.rs +expression: output +--- +// This code is @generated by cw-schema-codegen. Do not modify this manually. + + +import { z } from 'zod'; + + +/** + + */ + +const typescript_utils_OwoSchema = + + z.object({ + + /** + + */ + + field_1: z.string().or(z.number()), + + /** + + */ + + field_2: z.string(), + +}) + +; + +type typescript_utils_Owo = z.infer; + +export { typescript_utils_Owo, typescript_utils_OwoSchema }; diff --git a/packages/cw-schema-codegen/tests/ts-e2e/.gitignore b/packages/cw-schema-codegen/tests/ts-e2e/.gitignore new file mode 100644 index 0000000000..83595e5566 --- /dev/null +++ b/packages/cw-schema-codegen/tests/ts-e2e/.gitignore @@ -0,0 +1,2 @@ +/node_modules +/src/gen.ts \ No newline at end of file diff --git a/packages/cw-schema-codegen/tests/ts-e2e/package-lock.json b/packages/cw-schema-codegen/tests/ts-e2e/package-lock.json new file mode 100644 index 0000000000..ffdeb6df5b --- /dev/null +++ b/packages/cw-schema-codegen/tests/ts-e2e/package-lock.json @@ -0,0 +1,575 @@ +{ + "name": "ts-e2e", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "ts-e2e", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "zod": "^3.23.8" + }, + "devDependencies": { + "@types/node": "^22.9.3", + "tslib": "^2.8.1", + "tsx": "^4.19.2", + "typescript": "^5.7.2" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@types/node": { + "version": "22.9.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.3.tgz", + "integrity": "sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", + "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.23.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/packages/cw-schema-codegen/tests/ts-e2e/package.json b/packages/cw-schema-codegen/tests/ts-e2e/package.json new file mode 100644 index 0000000000..9a6c923500 --- /dev/null +++ b/packages/cw-schema-codegen/tests/ts-e2e/package.json @@ -0,0 +1,22 @@ +{ + "name": "ts-e2e", + "version": "0.1.0", + "type": "module", + "main": "index.ts", + "private": true, + "scripts": { + "test": "tsx src/index.ts" + }, + "author": "", + "license": "MIT", + "description": "", + "devDependencies": { + "@types/node": "^22.9.3", + "tslib": "^2.8.1", + "tsx": "^4.19.2", + "typescript": "^5.7.2" + }, + "dependencies": { + "zod": "^3.23.8" + } +} diff --git a/packages/cw-schema-codegen/tests/ts-e2e/src/index.ts b/packages/cw-schema-codegen/tests/ts-e2e/src/index.ts new file mode 100644 index 0000000000..00ecd472c9 --- /dev/null +++ b/packages/cw-schema-codegen/tests/ts-e2e/src/index.ts @@ -0,0 +1,22 @@ +import * as gen from './gen'; +import process from 'node:process'; + +async function read(stream: NodeJS.ReadStream): Promise { + const chunks: any[] = []; + for await (const chunk of stream) chunks.push(chunk); + return Buffer.concat(chunks).toString('utf8'); +} + +const stdinString = await read(process.stdin); + +// Match based on the argument, then attempt to deserialize and validate. Then re-serialize and emit. +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/ts-e2e/tsconfig.json b/packages/cw-schema-codegen/tests/ts-e2e/tsconfig.json new file mode 100644 index 0000000000..5910b38c60 --- /dev/null +++ b/packages/cw-schema-codegen/tests/ts-e2e/tsconfig.json @@ -0,0 +1,111 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "Es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "ES2022", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "bundler", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/packages/cw-schema-codegen/tests/typescript.rs b/packages/cw-schema-codegen/tests/typescript.rs new file mode 100644 index 0000000000..2af2f8accc --- /dev/null +++ b/packages/cw-schema-codegen/tests/typescript.rs @@ -0,0 +1,66 @@ +use core::str; +use std::{fs::File, io::Write, process::Command}; + +use crate::utils::TestCase; + +mod utils; + +#[test] +fn codegen_snap() { + // generate the schemas for each of the above types + let schemas = [ + cw_schema::schema_of::(), + cw_schema::schema_of::(), + cw_schema::schema_of::(), + cw_schema::schema_of::(), + cw_schema::schema_of::(), + ]; + + // run the codegen to typescript + for schema in schemas { + let cw_schema::Schema::V1(schema) = schema else { + panic!(); + }; + + let output = schema + .definitions + .iter() + .map(|node| { + let mut buf = Vec::new(); + cw_schema_codegen::typescript::process_node(&mut buf, &schema, node, true).unwrap(); + String::from_utf8(buf).unwrap() + }) + .collect::(); + + insta::assert_snapshot!(output); + } +} + +#[test] +#[ignore] // because it requires NPM to be installed, CI will still run it +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()); + + utils::run_e2e( + |buf, schema, node| cw_schema_codegen::typescript::process_node(buf, schema, node, true), + |TestCase { code, type_name }| { + let mut gen_file = File::create(&gen_file_path).unwrap(); + gen_file.write_all(code.as_bytes()).unwrap(); + + let mut cmd = Command::new("npm"); + cmd.args(["test".into(), format!("{type_name}Schema")]) + .current_dir(&e2e_dir); + + cmd + }, + ); +} diff --git a/packages/cw-schema-codegen/tests/utils.rs b/packages/cw-schema-codegen/tests/utils.rs new file mode 100644 index 0000000000..6ccc881236 --- /dev/null +++ b/packages/cw-schema-codegen/tests/utils.rs @@ -0,0 +1,180 @@ +use std::{ + collections::BTreeMap, + io::{self, Write}, + process::{Command, Stdio}, +}; + +use arbitrary::Arbitrary; +use cw_schema::Schemaifier; +use serde::{Deserialize, Serialize}; + +#[derive(Arbitrary, Schemaifier, Debug, Deserialize, PartialEq, Serialize)] +pub struct Owo { + field_1: u32, + field_2: String, +} + +#[derive(Arbitrary, Schemaifier, Debug, Deserialize, PartialEq, Serialize)] +pub struct Uwu(String, u32); + +#[derive(Arbitrary, Schemaifier, Debug, Deserialize, PartialEq, Serialize)] +pub struct Òwó; + +#[derive(Schemaifier, Debug, Deserialize, PartialEq, Serialize)] +pub enum Empty {} + +#[derive(Arbitrary, Schemaifier, Debug, Deserialize, PartialEq, Serialize)] +pub enum Hehehe { + A, + B(u32), + C { field: String }, +} + +#[derive(Arbitrary, Schemaifier, Debug, Deserialize, PartialEq, Serialize)] +pub struct Foo { + // foo_field_0: f32, // can cause rounding errors + // foo_field_1: f64, + foo_field_2: bool, + foo_field_3: String, + // foo_field_4: i128, // not supported on all platforms (e.g. Go) + foo_field_4: i32, + foo_field_5: u8, + foo_field_6: Vec, + foo_field_7: Option, + foo_field_9: Box, + foo_field_10: BTreeMap, + foo_field_11: (u32, String), +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(untagged)] +pub enum Combined { + Owo(Owo), + Uwu(Uwu), + Òwó(Òwó), + Empty(Empty), + Hehehe(Hehehe), + Foo(Foo), +} + +macro_rules! impl_from { + ($ty:ident) => { + impl From<$ty> for Combined { + fn from(ty: $ty) -> Combined { + Combined::$ty(ty) + } + } + }; +} + +impl_from!(Owo); +impl_from!(Uwu); +impl_from!(Òwó); +impl_from!(Empty); +impl_from!(Hehehe); +impl_from!(Foo); + +fn wrap Arbitrary<'a> + Into>( + stuff: &mut arbitrary::Unstructured, +) -> Combined { + T::arbitrary(stuff).unwrap().into() +} + +fn type_name() -> String { + std::any::type_name::() + .replace("::", "_") + .replace(['<', '>'], "_") +} + +pub struct TestCase<'a> { + pub code: &'a str, + pub type_name: &'a str, +} + +pub fn run_e2e( + process_node: impl Fn(&mut Vec, &cw_schema::SchemaV1, &cw_schema::Node) -> io::Result<()>, + mut run_code: impl FnMut(TestCase) -> Command, +) { + #[allow(clippy::type_complexity)] + let schemas: &[(_, fn(&mut arbitrary::Unstructured<'_>) -> Combined, _)] = &[ + ( + cw_schema::schema_of::(), + wrap::, + type_name::(), + ), + ( + cw_schema::schema_of::(), + wrap::, + type_name::(), + ), + ( + cw_schema::schema_of::<Òwó>(), + wrap::<Òwó>, + type_name::<Òwó>(), + ), + // `Empty` is a non-constructable type + /*( + cw_schema::schema_of::(), + wrap::, + type_name::(), + ),*/ + ( + cw_schema::schema_of::(), + wrap::, + type_name::(), + ), + ( + cw_schema::schema_of::(), + wrap::, + type_name::(), + ), + ]; + + let random_data: [u8; 255] = rand::random(); + let mut unstructured = arbitrary::Unstructured::new(&random_data); + for (schema, arbitrary_gen, type_name) in schemas { + let cw_schema::Schema::V1(schema) = schema else { + unreachable!(); + }; + + let output = schema + .definitions + .iter() + .map(|node| { + let mut buf = Vec::new(); + process_node(&mut buf, schema, node).unwrap(); + String::from_utf8(buf).unwrap() + }) + .collect::(); + + let data = arbitrary_gen(&mut unstructured); + let serialized = serde_json::to_string(&data).unwrap(); + let mut child = run_code(TestCase { + code: &output, + type_name, + }) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .unwrap(); + + { + let mut stdin = child.stdin.take().unwrap(); + stdin.write_all(serialized.as_bytes()).unwrap(); + } + + let proc_output = child.wait_with_output().unwrap(); + assert!( + proc_output.status.success(), + "failed with object: {data:#?}; json: {serialized}; schema: {output}" + ); + + let stdout = core::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); + } +} diff --git a/packages/schema/src/lib.rs b/packages/schema/src/lib.rs index 36698f8879..28fbe9884e 100644 --- a/packages/schema/src/lib.rs +++ b/packages/schema/src/lib.rs @@ -97,3 +97,6 @@ pub use cosmwasm_schema_derive::write_api; pub use cw_schema; pub use schemars; pub use serde; + +#[doc(hidden)] +pub use self::idl::JsonCwApi;