diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f356ca5b..a75c7742 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,12 +15,12 @@ jobs: - name: dependencies e2e test working-directory: e2e/dependencies/consumer run: | - cargo t - tsc bindings/* --noEmit --noUnusedLocals --strict + cargo t --features ts-rs/export + tsc bindings/*.ts --noEmit --noUnusedLocals --strict - name: dependencies e2e test with default export env working-directory: e2e/dependencies/consumer run: | - TS_RS_EXPORT_DIR=custom-bindings cargo t + TS_RS_EXPORT_DIR=custom-bindings cargo t --features ts-rs/export shopt -s globstar tsc custom-bindings/**/*.ts --noEmit --noUnusedLocals --strict e2e-workspace: @@ -37,14 +37,14 @@ jobs: - name: workspace e2e test working-directory: e2e/workspace run: | - cargo t + cargo t --features ts-rs/export shopt -s globstar tsc parent/bindings/**/*.ts --noEmit --noUnusedLocals --strict rm -rf parent/bindings - name: workspace e2e with default export env working-directory: e2e/workspace run: | - TS_RS_EXPORT_DIR=custom-bindings cargo t + TS_RS_EXPORT_DIR=custom-bindings cargo t --features ts-rs/export shopt -s globstar tsc parent/custom-bindings/**/*.ts --noEmit --noUnusedLocals --strict rm -rf parent/custom-bindings @@ -62,12 +62,12 @@ jobs: - name: example e2e test working-directory: example run: | - cargo t - tsc bindings/* --noEmit + cargo t --features ts-rs/export + tsc bindings/*.ts --noEmit - name: example e2e with default export env working-directory: example run: | - TS_RS_EXPORT_DIR=custom-bindings cargo t + TS_RS_EXPORT_DIR=custom-bindings cargo t --features ts-rs/export shopt -s globstar tsc custom-bindings/**/*.ts --noEmit --noUnusedLocals --strict @@ -143,7 +143,7 @@ jobs: - name: Test working-directory: ts-rs run: | - TS_RS_EXPORT_DIR=output cargo test --no-default-features + TS_RS_EXPORT_DIR=output cargo test --no-default-features --features ts-rs/export shopt -s globstar tsc output/**/*.ts --noEmit --noUnusedLocals --strict rm -rf output @@ -162,7 +162,7 @@ jobs: - name: Test working-directory: ts-rs run: | - TS_RS_EXPORT_DIR=$(pwd)/output cargo test --no-default-features + TS_RS_EXPORT_DIR=$(pwd)/output cargo test --no-default-features --features ts-rs/export shopt -s globstar tsc output/**/*.ts --noEmit --noUnusedLocals --strict rm -rf output @@ -181,7 +181,7 @@ jobs: - name: Test working-directory: ts-rs run: | - cargo test --no-default-features + cargo test --no-default-features --features ts-rs/export shopt -s globstar tsc bindings/**/*.ts --noEmit --noUnusedLocals rm -rf bindings diff --git a/.gitignore b/.gitignore index f5541831..f8bdb731 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ target/ tsconfig.json /ts-rs/tests-out +ts_rs.meta \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 68a217fe..d342fd17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,18 +14,18 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.24.2" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] [[package]] -name = "adler2" -version = "2.0.0" +name = "adler" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" @@ -34,7 +34,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.2.15", "once_cell", "version_check", "zerocopy", @@ -51,9 +51,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" @@ -70,11 +70,61 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +dependencies = [ + "anstyle", + "once_cell", + "windows-sys", +] + [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" [[package]] name = "ast_node" @@ -85,7 +135,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -96,17 +146,17 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", + "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", - "windows-targets", ] [[package]] @@ -126,9 +176,9 @@ dependencies = [ [[package]] name = "bigdecimal" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f850665a0385e070b64c38d2354e6c104c8479c59868d1e48a0c13ee2c7a1c1" +checksum = "7f31f3af01c5c65a07985c804d3366560e6fa7883d640a122819b14ec327482c" dependencies = [ "autocfg", "libm", @@ -140,9 +190,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bitvec" @@ -158,9 +208,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" +checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc" dependencies = [ "cfg_aliases", ] @@ -188,9 +238,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" dependencies = [ "allocator-api2", ] @@ -203,15 +253,23 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" + +[[package]] +name = "cargo-ts" +version = "0.1.0" +dependencies = [ + "clap", + "color-eyre", +] [[package]] name = "cc" -version = "1.2.2" +version = "1.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" +checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af" dependencies = [ "shlex", ] @@ -230,9 +288,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -243,6 +301,79 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "clap" +version = "4.5.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "color-eyre" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -316,7 +447,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -384,9 +515,9 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "example" @@ -398,6 +529,16 @@ dependencies = [ "uuid", ] +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -415,7 +556,7 @@ checksum = "32016f1242eb82af5474752d00fd8ebcd9004bd69b462b1c91de833972d08ed4" dependencies = [ "proc-macro2", "swc_macros_common", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -432,14 +573,26 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets", ] [[package]] name = "gimli" -version = "0.31.1" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "hash32" @@ -490,9 +643,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hstr" -version = "0.2.12" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dae404c0c5d4e95d4858876ab02eecd6a196bb8caa42050dfa809938833fc412" +checksum = "a1a26def229ea95a8709dad32868d975d0dd40235bd2ce82920e4a8fe692b5e0" dependencies = [ "hashbrown 0.14.5", "new_debug_unreachable", @@ -640,7 +793,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -664,11 +817,17 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "indexmap" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -684,9 +843,15 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itoa" version = "1.0.14" @@ -695,9 +860,9 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.74" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -711,9 +876,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.167" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libm" @@ -729,9 +894,9 @@ checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "log" -version = "0.4.22" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "memchr" @@ -741,11 +906,11 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ - "adler2", + "adler", ] [[package]] @@ -791,28 +956,34 @@ dependencies = [ [[package]] name = "object" -version = "0.36.5" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.20.2" +version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "ordered-float" -version = "4.5.0" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c65ee1f9701bf938026630b455d5315f490640234259037edb259798b3bcf85e" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" dependencies = [ "num-traits", ] +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -821,9 +992,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", "phf_shared", @@ -831,9 +1002,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", "rand", @@ -841,31 +1012,31 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ "phf_generator", "phf_shared", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher", + "siphasher 1.0.1", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "powerfmt" @@ -884,27 +1055,27 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "psm" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" +checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88" dependencies = [ "cc", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -942,7 +1113,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -986,11 +1157,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "scoped-tls" @@ -1000,15 +1177,15 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] @@ -1024,20 +1201,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" dependencies = [ "indexmap", "itoa", @@ -1046,6 +1223,15 @@ dependencies = [ "serde", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1058,11 +1244,17 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "smallvec" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" [[package]] name = "smartstring" @@ -1093,9 +1285,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stacker" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" +checksum = "d9156ebd5870ef293bfb43f91c7a74528d363ec0d424afe24160ed5a4343d08a" dependencies = [ "cc", "cfg-if", @@ -1119,9 +1311,15 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.90", + "syn 2.0.98", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "swc_atoms" version = "0.6.7" @@ -1150,7 +1348,7 @@ dependencies = [ "once_cell", "rustc-hash", "serde", - "siphasher", + "siphasher 0.3.11", "swc_atoms", "swc_eq_ignore_macros", "swc_visit", @@ -1207,7 +1405,7 @@ checksum = "695a1d8b461033d32429b5befbf0ad4d7a2c4d6ba9cd5ba4e0645c615839e8e4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -1218,7 +1416,7 @@ checksum = "27e18fbfe83811ffae2bb23727e45829a0d19c6870bced7c0f545cc99ad248dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -1241,7 +1439,7 @@ dependencies = [ "proc-macro2", "quote", "swc_macros_common", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -1257,9 +1455,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -1274,7 +1472,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -1312,11 +1510,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.11", ] [[package]] @@ -1327,25 +1525,35 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", ] [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -1364,9 +1572,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -1384,9 +1592,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.41.1" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "pin-project-lite", @@ -1411,7 +1619,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -1421,6 +1629,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", ] [[package]] @@ -1449,7 +1679,7 @@ dependencies = [ "serde", "serde_json", "smol_str", - "thiserror 2.0.3", + "thiserror 2.0.11", "tokio", "ts-rs-macros", "url", @@ -1462,7 +1692,7 @@ version = "10.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", "termcolor", ] @@ -1480,9 +1710,9 @@ checksum = "02aebfa694eccbbbffdd92922c7de136b9fe764396d2f10e21bce1681477cfc1" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" [[package]] name = "unicode-width" @@ -1514,16 +1744,28 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" -version = "1.11.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +checksum = "93d59ca99a559661b96bf898d8fce28ed87935fd2bea9f05983c1464dd6c71b1" dependencies = [ - "getrandom", + "getrandom 0.3.1", "serde", ] +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "version_check" version = "0.9.5" @@ -1536,37 +1778,46 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" -version = "0.2.97" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.97" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.97" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1574,22 +1825,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.97" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.97" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "winapi-util" @@ -1682,6 +1936,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + [[package]] name = "write16" version = "1.0.0" @@ -1723,7 +1986,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", "synstructure", ] @@ -1745,7 +2008,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] [[package]] @@ -1765,7 +2028,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", "synstructure", ] @@ -1788,5 +2051,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.98", ] diff --git a/Cargo.toml b/Cargo.toml index 3afd3eec..2269bbc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,4 @@ [workspace] -members = ["macros", "ts-rs", "example"] +members = ["macros", "ts-rs", "example", "cli"] resolver = "2" diff --git a/cli/Cargo.toml b/cli/Cargo.toml new file mode 100644 index 00000000..1236df2a --- /dev/null +++ b/cli/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "cargo-ts" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4", features = ["derive"]} +color-eyre = "0.6" diff --git a/cli/src/args.rs b/cli/src/args.rs new file mode 100644 index 00000000..86cde5f8 --- /dev/null +++ b/cli/src/args.rs @@ -0,0 +1,48 @@ +use std::path::PathBuf; + +use clap::Parser; + +use crate::metadata::FILE_NAME; + +#[derive(Parser, Debug)] +#[allow(clippy::struct_excessive_bools)] +pub struct Args { + /// Defines where your TS bindings will be saved by setting TS_RS_EXPORT_DIR + #[arg(long, short)] + pub output_directory: PathBuf, + + /// Disables warnings caused by using serde attributes that ts-rs cannot process + #[arg(long)] + pub no_warnings: bool, + + /// Adds the ".js" extension to import paths + #[arg(long)] + pub esm_imports: bool, + + /// Formats the generated TypeScript files + #[arg(long)] + pub format: bool, + + /// Generates an index.ts file in your --output-directory that re-exports all + /// types generated by ts-rs + #[arg(long = "index")] + pub generate_index_ts: bool, + + /// Generates only a single index.ts file in your --output-directory that + /// contains all exported types + #[arg(long = "merge")] + pub merge_files: bool, + + /// Do not capture `cargo test`'s output, and pass --nocapture to the test binary + #[arg(long = "nocapture")] + pub no_capture: bool, +} + +// Args is in scope for the entirety of the main function, so this will only +// be executed when the program is finished running. This helps prevent us +// from forgetting to do cleanup if some code branch early returns from main +impl Drop for Args { + fn drop(&mut self) { + _ = std::fs::remove_file(self.output_directory.join(FILE_NAME)); + } +} diff --git a/cli/src/cargo.rs b/cli/src/cargo.rs new file mode 100644 index 00000000..a9695f24 --- /dev/null +++ b/cli/src/cargo.rs @@ -0,0 +1,51 @@ +use std::process::{Command, Stdio}; + +use color_eyre::Result; + +use crate::{args::Args, path}; + +macro_rules! feature { + ($cargo_invocation: expr, $args: expr, { $($field: ident => $feature: literal),* $(,)? }) => { + $( + if $args.$field { + $cargo_invocation + .arg("--features") + .arg(format!("ts-rs/{}", $feature)); + } + )* + }; +} + +pub fn invoke(args: &Args) -> Result<()> { + let mut cargo_invocation = Command::new("cargo"); + + cargo_invocation + .arg("test") + .arg("export_bindings_") + .arg("--features") + .arg("ts-rs/export") + .arg("--features") + .arg("ts-rs/generate-metadata") + .stdout(if args.no_capture { + Stdio::inherit() + } else { + Stdio::piped() + }) + .env("TS_RS_EXPORT_DIR", path::absolute(&args.output_directory)?); + + feature!(cargo_invocation, args, { + no_warnings => "no-serde-warnings", + esm_imports => "import-esm", + format => "format", + }); + + if args.no_capture { + cargo_invocation.arg("--").arg("--nocapture"); + } else { + cargo_invocation.arg("--quiet"); + } + + cargo_invocation.spawn()?.wait()?; + + Ok(()) +} diff --git a/cli/src/main.rs b/cli/src/main.rs new file mode 100644 index 00000000..005684c5 --- /dev/null +++ b/cli/src/main.rs @@ -0,0 +1,107 @@ +#![warn(clippy::pedantic, clippy::nursery)] + +use std::{ + fs::{self, OpenOptions}, + io::{Read, Write}, +}; + +use clap::Parser; +use color_eyre::{owo_colors::OwoColorize, Result}; + +mod args; +mod cargo; +mod metadata; +mod path; + +use args::Args; +use metadata::{Metadata, FILE_NAME}; + +const BLANK_LINE: [u8; 2] = [b'\n', b'\n']; +const NOTE: &[u8; 109] = b"// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.\n"; + +fn main() -> Result<()> { + color_eyre::install()?; + + let args = Args::parse(); + + let metadata_path = args.output_directory.join(FILE_NAME); + if metadata_path.exists() { + fs::remove_file(&metadata_path)?; + } + + if args.merge_files && args.generate_index_ts { + eprintln!( + "{} --index is not compatible with --merge", + "Error:".red().bold() + ); + + return Ok(()); + } + + cargo::invoke(&args)?; + + let metadata_content = fs::read_to_string(&metadata_path)?; + let metadata = Metadata::try_from(&*metadata_content)?; + + let demand_unique_names = args.merge_files || args.generate_index_ts; + + if !demand_unique_names || metadata.is_empty() { + return Ok(()); + } + + if metadata.has_naming_collisions() { + metadata.report_naming_collisions(); + + eprintln!( + "{} due to the naming collisions listed above, generating an index.ts file is not possible", + "Error:".red().bold() + ); + + return Ok(()); + } + + let index_path = args.output_directory.join("index.ts"); + + if index_path.exists() { + fs::remove_file(&index_path)?; + } + + let mut index = OpenOptions::new() + .create(true) + .append(true) + .open(index_path)?; + + index.write_all(NOTE)?; + + if args.generate_index_ts { + for path in metadata.export_paths() { + index.write_fmt(format_args!("\nexport * from {path:?};"))?; + } + + return Ok(()); + } + + if args.merge_files { + for path in metadata.export_paths() { + let path = path::absolute(args.output_directory.join(path))?; + let mut file = OpenOptions::new().read(true).open(&path)?; + + let mut buf = Vec::with_capacity(file.metadata()?.len().try_into()?); + file.read_to_end(&mut buf)?; + + let Some((i, _)) = buf.windows(2).enumerate().find(|(_, w)| w == &BLANK_LINE) else { + continue; + }; + + index.write_all(&buf[i + 1..])?; + + fs::remove_file(path)?; + } + + path::remove_empty_subdirectories(&args.output_directory)?; + + return Ok(()); + } + + Ok(()) +} diff --git a/cli/src/metadata.rs b/cli/src/metadata.rs new file mode 100644 index 00000000..e04cc2bf --- /dev/null +++ b/cli/src/metadata.rs @@ -0,0 +1,104 @@ +use std::{ + collections::{HashMap, HashSet}, + path::Path, +}; + +use color_eyre::{ + eyre::{Error, OptionExt}, + owo_colors::OwoColorize, + Result, +}; + +pub const FILE_NAME: &str = "ts_rs.meta"; + +pub struct Metadata<'a> { + entries: std::collections::HashMap<&'a str, HashSet>>, +} + +impl<'a> TryFrom<&'a str> for Metadata<'a> { + type Error = Error; + + fn try_from(value: &'a str) -> Result { + Ok(Self { + entries: value.lines().try_fold( + HashMap::<&str, HashSet<_>>::default(), + |mut acc, cur| { + let (key, value) = cur.split_once(',').ok_or_eyre("Invalid metadata file")?; + let value = Entry::try_from(value)?; + + acc.entry(key).or_default().insert(value); + + Ok::<_, Error>(acc) + }, + )?, + }) + } +} + +impl<'a> Metadata<'a> { + pub fn is_empty(&self) -> bool { + self.entries.is_empty() + } + + pub fn has_naming_collisions(&self) -> bool { + self.entries.values().any(|x| x.len() > 1) + } + + pub fn report_naming_collisions(&self) { + self.entries + .iter() + .filter(|(_, x)| x.len() > 1) + .for_each(|(ty, entry)| name_collision_warning(ty, entry)); + } + + pub fn export_paths(&self) -> impl Iterator { + self.entries.values().flatten().map(|x| x.export_path) + } +} + +#[derive(PartialEq, Eq, Hash)] +struct Entry<'a> { + rust_name: &'a str, + export_path: &'a Path, +} + +impl<'a> TryFrom<&'a str> for Entry<'a> { + type Error = Error; + + fn try_from(value: &'a str) -> Result { + let (rust_name, export_path) = + value.split_once(',').ok_or_eyre("Invalid metadata entry")?; + + Ok(Self { + rust_name, + export_path: Path::new(export_path), + }) + } +} + +fn name_collision_warning(ts_type: &str, metadata: &HashSet) { + eprintln!( + "{} Multiple types being exported with the name \"{}\"", + "Warning:".yellow().bold(), + ts_type.green().bold() + ); + + for entry in metadata { + eprintln!( + " {} {} {}", + "-".blue().bold(), + "Type:".bold(), + entry.rust_name.cyan(), + ); + + eprintln!( + " {} {}", + "Path:".bold(), + entry.export_path.to_string_lossy() + ); + + eprintln!(); + } + + eprintln!(); +} diff --git a/cli/src/path.rs b/cli/src/path.rs new file mode 100644 index 00000000..6e4255e3 --- /dev/null +++ b/cli/src/path.rs @@ -0,0 +1,64 @@ +use std::{ + fs, + io::ErrorKind, + path::{Component as C, Path, PathBuf}, +}; + +use color_eyre::{eyre::OptionExt, Result}; + +pub fn absolute>(path: T) -> Result { + let path = path.as_ref(); + + if path.is_absolute() { + return Ok(path.to_owned()); + } + + let path = std::env::current_dir()?.join(path); + + let mut out = Vec::new(); + for comp in path.components() { + match comp { + C::CurDir => (), + C::ParentDir => { + out.pop().ok_or_eyre("Invalid path")?; + } + comp => out.push(comp), + } + } + + Ok(if out.is_empty() { + PathBuf::from(".") + } else { + out.iter().collect() + }) +} + +pub fn remove_empty_subdirectories>(path: T) -> Result<()> { + let path = path.as_ref(); + + for entry in path.read_dir()? { + let entry = entry?; + + let path = entry.path(); + + if !path.is_dir() { + continue; + } + + remove_empty_subdirectories(&path)?; + if let Err(e) = fs::remove_dir(path) { + // The other possible error kinds are either not available + // in stable rust (DirectoryNotEmpty), not possible due + // to the logic of this function (NotFound) or both (NotADirectory) + // + // The correct check would be `!matches!(e.kind(), ErrorKind::DirectoryNotEmpty)` + // as that is the only error we actually WANT to ignore... the others, + // although impossible, should be returned if they somehow happen + if matches!(e.kind(), ErrorKind::PermissionDenied) { + return Err(e.into()); + } + } + } + + Ok(()) +} diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 28510266..c1e140f0 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -11,6 +11,7 @@ repository = "https://github.com/Aleph-Alpha/ts-rs" [features] serde-compat = ["termcolor"] no-serde-warnings = [] +export = [] [lib] proc-macro = true diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 8f4eecc1..78b8c009 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -35,9 +35,8 @@ struct DerivedTS { impl DerivedTS { fn into_impl(mut self, rust_ty: Ident, generics: Generics) -> TokenStream { - let export = self - .export - .then(|| self.generate_export_test(&rust_ty, &generics)); + let allow_export = cfg!(feature = "export") && self.export; + let export = allow_export.then(|| self.generate_export_test(&rust_ty, &generics)); let output_path_fn = { let ts_name = &self.ts_name; diff --git a/macros/src/utils.rs b/macros/src/utils.rs index 7bd04b8c..238aed89 100644 --- a/macros/src/utils.rs +++ b/macros/src/utils.rs @@ -235,7 +235,7 @@ pub(crate) mod warning { let mut buffer = writer.buffer(); buffer.set_color(&yellow_bold)?; - write!(&mut buffer, "warning")?; + write!(&mut buffer, "Warning")?; buffer.set_color(&white_bold)?; writeln!(&mut buffer, ": {}", title)?; diff --git a/ts-rs/Cargo.toml b/ts-rs/Cargo.toml index 2c0cbe02..f64e297c 100644 --- a/ts-rs/Cargo.toml +++ b/ts-rs/Cargo.toml @@ -35,6 +35,8 @@ smol_str-impl = ["smol_str"] serde-json-impl = ["serde_json"] no-serde-warnings = ["ts-rs-macros/no-serde-warnings"] import-esm = [] +export = ["ts-rs-macros/export"] +generate-metadata = [] tokio-impl = ["tokio"] [dev-dependencies] diff --git a/ts-rs/src/export.rs b/ts-rs/src/export.rs index 420799de..730a429b 100644 --- a/ts-rs/src/export.rs +++ b/ts-rs/src/export.rs @@ -126,14 +126,14 @@ pub(crate) fn export_to>( std::fs::create_dir_all(parent)?; } - export_and_merge(path, type_name, buffer)?; + export_and_merge::(path, type_name, buffer)?; Ok(()) } /// Exports the type to a new file if the file hasn't yet been written to. /// Otherwise, finds its place in the already existing file and inserts it. -fn export_and_merge( +fn export_and_merge( path: PathBuf, type_name: String, generated_type: String, @@ -142,6 +142,25 @@ fn export_and_merge( let lock = &mut get_export_paths().lock().unwrap(); + if cfg!(feature = "generate-metadata") { + let relative_path = T::output_path() + .ok_or_else(std::any::type_name::) + .map_err(ExportError::CannotBeExported)? + .to_string_lossy() + .into_owned(); + + let type_ts_name = T::ident(); + let type_rs_name = std::any::type_name::().split('<').next().unwrap(); + + std::fs::OpenOptions::new() + .append(true) + .create(true) + .open(default_out_dir().join("ts_rs.meta"))? + .write_fmt(format_args!( + "{type_ts_name},{type_rs_name},./{relative_path}\n" + ))?; + } + let Some(entry) = lock.get_mut(&path) else { // The file hasn't been written to yet, so it must be // overwritten diff --git a/ts-rs/tests/integration/issue_308.rs b/ts-rs/tests/integration/issue_308.rs index 524d028d..8f2e567b 100644 --- a/ts-rs/tests/integration/issue_308.rs +++ b/ts-rs/tests/integration/issue_308.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use ts_rs::{Dependency, ExportError, TypeVisitor, TS}; +use ts_rs::{TypeVisitor, Dependency, ExportError, TS}; #[rustfmt::skip] trait Malicious { diff --git a/ts-rs/tests/integration/path_bug.rs b/ts-rs/tests/integration/path_bug.rs index 12ade1bf..4c48c6ba 100644 --- a/ts-rs/tests/integration/path_bug.rs +++ b/ts-rs/tests/integration/path_bug.rs @@ -2,7 +2,7 @@ use ts_rs::TS; #[derive(TS)] -#[ts(export, export_to = "path_bug/aaa/")] +#[ts(export_to = "path_bug/aaa/")] struct Foo { bar: Bar, } @@ -15,7 +15,7 @@ struct Bar { #[test] fn path_bug() { - export_bindings_foo(); + Foo::export_all().unwrap(); assert!(Foo::default_output_path().unwrap().is_file()); assert!(Bar::default_output_path().unwrap().is_file()); diff --git a/ts-rs/tests/integration/recursion_limit.rs b/ts-rs/tests/integration/recursion_limit.rs index 16e1a2d2..fb9738c7 100644 --- a/ts-rs/tests/integration/recursion_limit.rs +++ b/ts-rs/tests/integration/recursion_limit.rs @@ -1,3 +1,5 @@ +#![allow(clippy::upper_case_acronyms)] + use std::any::TypeId; use ts_rs::{TypeVisitor, TS};