commit fe3ec74e35c0975e5936bffc681eee0cc7cff63b Author: Sandipsinh Rathod Date: Thu Dec 19 19:42:36 2024 -0500 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..53feb16 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1460 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[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 2.0.90", +] + +[[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 2.0.90", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "unicode-xid", +] + +[[package]] +name = "derive_setters" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e8ef033054e131169b8f0f9a7af8f5533a9436fadf3c500ed547f730f07090d" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[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 = "foo" +version = "0.1.0" +dependencies = [ + "anyhow", + "convert_case", + "lazy_static", + "oapi", + "oas3", + "openapi3-parser", + "protox", + "protox-parse", + "schemars", + "serde", + "serde_json", + "serde_yaml 0.9.34+deprecated", + "sppparse", + "tailcall-valid", + "wit-parser", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getset" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f636605b743120a8d32ed92fc27b6cde1a769f8f936c065151eb66f88ded513c" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "http" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", + "serde", +] + +[[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 = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libyml" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980" +dependencies = [ + "anyhow", + "version_check", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "logos" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7251356ef8cb7aec833ddf598c6cb24d17b689d20b993f9d11a3d764e34e6458" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59f80069600c0d66734f5ff52cc42f2dabd6b29d205f333d61fd7832e9e9963f" +dependencies = [ + "beef", + "fnv", + "lazy_static", + "proc-macro2", + "quote", + "regex-syntax", + "syn 2.0.90", +] + +[[package]] +name = "logos-derive" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24fb722b06a9dc12adb0963ed585f19fc61dc5413e6a9be9422ef92c091e731d" +dependencies = [ + "logos-codegen", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miette" +version = "7.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317f146e2eb7021892722af37cf1b971f0a70c8406f487e24952667616192c64" +dependencies = [ + "cfg-if", + "miette-derive", + "thiserror 1.0.69", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "7.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c9b935fbe1d6cbd1dac857b54a688145e2d93f48db36010514d0f612d0ad67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "oapi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48b622efb326be8045075dcc476b19de84ddb8d50555b2cbd4af8be6b2e5487c" +dependencies = [ + "getset", + "oapi_derive", + "semver 0.11.0", + "serde", + "serde_json", + "sppparse", + "thiserror 1.0.69", +] + +[[package]] +name = "oapi_derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f92b74feb1092d6c09cfda09ceaa6337c73c136d812c121b06bc2e686b1dca" +dependencies = [ + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure 0.12.6", +] + +[[package]] +name = "oas3" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caad8a11807e43c49ab8f9527c96d0ec926f525549e65e5cd3b502115704a58e" +dependencies = [ + "derive_more", + "http", + "log", + "once_cell", + "regex", + "semver 1.0.24", + "serde", + "serde_json", + "serde_yml", + "url", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "openapi3-parser" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc3db890d49a234a788d2920ef231d191e7e56142c7fabbfe56bbefda3d20031" +dependencies = [ + "serde", + "serde_json", + "serde_yaml 0.9.34+deprecated", + "thiserror 1.0.69", +] + +[[package]] +name = "path-absolutize" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4af381fe79fa195b4909485d99f73a80792331df0625188e707854f0b3383f5" +dependencies = [ + "path-dedot", +] + +[[package]] +name = "path-clean" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecba01bf2678719532c5e3059e0b5f0811273d94b397088b82e3bd0a78c78fdd" + +[[package]] +name = "path-dedot" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ba0ad7e047712414213ff67533e6dd477af0a4e1d14fb52343e53d30ea9397" +dependencies = [ + "once_cell", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" +dependencies = [ + "memchr", + "thiserror 2.0.8", + "ucd-trie", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "prost-reflect" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20ae544fca2892fd4b7e9ff26cba1090cedf1d4d95c2aded1af15d2f93f270b8" +dependencies = [ + "logos", + "miette", + "once_cell", + "prost", + "prost-types", +] + +[[package]] +name = "prost-types" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2f1e56baa61e93533aebc21af4d2134b70f66275e0fcdf3cbe43d77ff7e8fc" +dependencies = [ + "prost", +] + +[[package]] +name = "protox" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "873f359bdecdfe6e353752f97cb9ee69368df55b16363ed2216da85e03232a58" +dependencies = [ + "bytes", + "miette", + "prost", + "prost-reflect", + "prost-types", + "protox-parse", + "thiserror 1.0.69", +] + +[[package]] +name = "protox-parse" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a462d115462c080ae000c29a47f0b3985737e5d3a995fcdbcaa5c782068dde" +dependencies = [ + "logos", + "miette", + "prost-types", + "thiserror 1.0.69", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[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 2.0.90", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[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", + "serde", + "serde_json", +] + +[[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 2.0.90", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", + "serde", +] + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" + +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[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 2.0.90", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" +dependencies = [ + "indexmap 1.9.3", + "ryu", + "serde", + "yaml-rust", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.7.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "serde_yml" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd" +dependencies = [ + "indexmap 2.7.0", + "itoa", + "libyml", + "memchr", + "ryu", + "serde", + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "sppparse" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac0a3329c1890f641ad6d145fcbfe590268401ec95f96d84940671fbc424f82a" +dependencies = [ + "getset", + "path-absolutize", + "path-clean", + "rand", + "semver 0.11.0", + "serde", + "serde_json", + "serde_path_to_error", + "serde_yaml 0.8.26", + "sppparse_derive", + "thiserror 1.0.69", + "url", +] + +[[package]] +name = "sppparse_derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7889b3dd4968cb7d6a77ef6a3e38141b9a15f9736fb9ef1401d3de09014de4a" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure 0.12.6", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tailcall-valid" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8071b2b6ff5cd941f96c743f1cd95043f76381e591d26f4858b5693bca604cee" +dependencies = [ + "derive_setters", + "http", + "regex", + "serde", + "serde_json", + "serde_path_to_error", + "thiserror 2.0.8", + "wasm-bindgen", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f5383f3e0071702bf93ab5ee99b52d26936be9dedd9413067cbdcddcb6141a" +dependencies = [ + "thiserror-impl 2.0.8", +] + +[[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 2.0.90", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f357fcec90b3caef6623a099691be676d033b40a058ac95d2a6ade6fa0c943" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.90", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" + +[[package]] +name = "wasmparser" +version = "0.222.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4adf50fde1b1a49c1add6a80d47aea500c88db70551805853aa8b88f3ea27ab5" +dependencies = [ + "bitflags", + "indexmap 2.7.0", + "semver 1.0.24", +] + +[[package]] +name = "wit-parser" +version = "0.222.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533abd14901514db88e4107655345fdd8ab8a72fb61e85d871bd361509744c35" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.7.0", + "log", + "semver 1.0.24", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure 0.13.1", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure 0.13.1", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..18c7d55 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "foo" +version = "0.1.0" +edition = "2021" + +[dependencies] +serde_json = "1.0.133" +serde_yaml = "0.9.34+deprecated" +schemars = "1.0.0-alpha.17" +anyhow = "1.0.94" +convert_case = "0.6.0" +protox = "0.7.1" +protox-parse = "0.7.0" +oapi = "0.1.2" +sppparse = "0.1.4" +oas3 = {version = "0.12.1", features = []} +openapi3-parser = { version = "0.1.0", features = [] } +serde = { version = "1.0.216", features = ["derive"] } +tailcall-valid = "0.1.3" +wit-parser = "0.222.0" +lazy_static = "1.5.0" + diff --git a/foo.proto b/foo.proto new file mode 100644 index 0000000..ff2852c --- /dev/null +++ b/foo.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; + +package core.todo.v1; + +message TodoListRequest {string user_id = 1;} + +message TodoAddRequest { + string user_id = 1; + string task = 2; +} + +message TodoDeleteRequest { + string user_id = 1; + string id = 2; +} + +message TodoObject { + string user_id = 1; + string id = 2; + string task = 3; +} + +message TodoChangeEvent { + string idemponcy_id = 1; + TodoObject current = 3; + TodoObject original = 4; +} + +message TodoAddResponse {TodoObject todo = 1;} +message TodoListResponse {repeated TodoObject todos = 1;} +message TodoDeleteResponse {string message = 1;} + +service TodoService { + rpc TodoAdd (TodoAddRequest) returns (TodoAddResponse); + rpc TodoDelete (TodoDeleteRequest) returns (TodoDeleteResponse); + rpc TodoList (TodoListRequest) returns (TodoListResponse); +} diff --git a/foo.wit b/foo.wit new file mode 100644 index 0000000..84b8e82 --- /dev/null +++ b/foo.wit @@ -0,0 +1,89 @@ +package api:todos@1.0.0; + +// Common types used across the API +interface types { + // Authentication types derived from OpenAPI security schemes + record bearer-token { + token: string, + } + + // Core resource type + record todo { + id: string, + title: string, + description: option, + completed: bool, + due-date: option, + user-id: string, + created-at: string, + updated-at: string, + } + + variant error { + unauthorized, + not-found, + validation-error(list), + rate-limited { retry-after: u32 }, + server-error, + } +} + +interface todos-collection { + use types.{todo, bearer-token, error}; + + // Request/response types with domain-appropriate fields + record list-request { + auth: bearer-token, + user-id: string, + status: option, + limit: option, + %offset: option, + } + + record list-response { + items: list, + total: u32, + limit: u32, + %offset: u32, + version: string, // From ETag + last-updated: option, // From Last-Modified + } + + record create-request { + auth: bearer-token, + title: string, + description: option, + due-date: option, + user-id: string, + } + + // Note: Response includes versioning info directly in return type + list: func(request: list-request) -> result; + + create: func(request: create-request) -> result; +} + +interface todos-resource { + use types.{todo, bearer-token, error}; + + record update-request { + auth: bearer-token, + title: option, + description: option, + completed: option, + due-date: option, + expected-version: option, // If-Match header + } + + get: func(id: string, auth: bearer-token) -> result; + + update: func(id: string, request: update-request) -> result; + + delete: func(id: string, auth: bearer-token) -> result; +} + +world todos-api { + export todos-collection; + export todos-resource; +} + diff --git a/foo.yml b/foo.yml new file mode 100644 index 0000000..18c2ad4 --- /dev/null +++ b/foo.yml @@ -0,0 +1,3190 @@ +openapi: 3.0.3 +info: + title: Todo REST API + description: A RESTful API for managing todo items + version: 1.0.0 +paths: + /todos: + get: + tags: null + summary: List todos + description: null + operationId: null + parameters: + - name: null + in: null + required: null + schema: null + description: null + example: null + examples: null + - name: null + in: null + required: null + schema: null + description: null + example: null + examples: null + - name: null + in: null + required: null + schema: null + description: null + example: null + examples: null + - name: null + in: null + required: null + schema: null + description: null + example: null + examples: null + - name: null + in: null + required: null + schema: null + description: null + example: null + examples: null + - name: null + in: null + required: null + schema: null + description: null + example: null + examples: null + requestBody: null + responses: + '401': + description: Unauthorized + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '200': + description: Successfully retrieved todos + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: + X-RateLimit-Reset: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: integer + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + X-RateLimit-Remaining: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: integer + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + Last-Modified: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + X-RateLimit-Limit: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: integer + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + X-Request-ID: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + ETag: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + '429': + description: Too many requests + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: + Retry-After: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: integer + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + '400': + description: Invalid parameters + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '500': + description: Internal server error + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + default: null + post: + tags: null + summary: Create a new todo + description: null + operationId: null + parameters: null + requestBody: + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + description: null + required: true + responses: + '500': + description: Internal server error + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '400': + description: Invalid input + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '201': + description: Todo created successfully + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: + ETag: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + X-Request-ID: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + Location: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: uri + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + '401': + description: Unauthorized + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + default: null + put: null + delete: null + patch: null + options: null + head: null + trace: null + /todos/{todoId}: + get: + tags: null + summary: Get a specific todo + description: null + operationId: null + parameters: null + requestBody: null + responses: + '404': + description: Todo not found + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '401': + description: Unauthorized + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '500': + description: Internal server error + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '200': + description: Successfully retrieved todo + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: + ETag: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + Last-Modified: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + X-Request-ID: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + default: null + post: null + put: null + delete: + tags: null + summary: Delete a todo + description: null + operationId: null + parameters: null + requestBody: null + responses: + '404': + description: Todo not found + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '500': + description: Internal server error + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '204': + description: Todo deleted successfully + content: null + headers: + X-Request-ID: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + '401': + description: Unauthorized + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + default: null + patch: + tags: null + summary: Update a todo + description: null + operationId: null + parameters: null + requestBody: + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + description: null + required: true + responses: + '500': + description: Internal server error + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '401': + description: Unauthorized + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '400': + description: Invalid input + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + '200': + description: Todo updated successfully + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: + X-Request-ID: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + ETag: + description: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + '404': + description: Todo not found + content: + application/json: + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + example: null + examples: null + headers: null + default: null + options: null + head: null + trace: null +components: + schemas: + TodoUpdate: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: 1 + required: null + type: object + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: + description: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: 2000 + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + dueDate: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: date-time + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + completed: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: boolean + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + title: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: 200 + minLength: 1 + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + Todo: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: + - id + - title + - completed + - userId + - createdAt + - updatedAt + type: object + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: + createdAt: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: date-time + default: null + nullable: null + discriminator: null + readOnly: true + writeOnly: null + xml: null + example: null + deprecated: null + updatedAt: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: date-time + default: null + nullable: null + discriminator: null + readOnly: true + writeOnly: null + xml: null + example: null + deprecated: null + userId: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + completed: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: boolean + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: false + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + dueDate: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: date-time + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + description: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: 2000 + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + title: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: 200 + minLength: 1 + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + id: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: uuid + default: null + nullable: null + discriminator: null + readOnly: true + writeOnly: null + xml: null + example: null + deprecated: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + TodoCreate: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: + - title + - userId + type: object + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: + title: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: 200 + minLength: 1 + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + description: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: 2000 + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + dueDate: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: date-time + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + userId: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + TodoList: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: + - data + - metadata + type: object + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: + data: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: array + not: null + allOf: null + oneOf: null + anyOf: null + items: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + metadata: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: + - total + - limit + - offset + type: object + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: + offset: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: 0.0 + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: integer + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + total: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: 0.0 + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: integer + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + limit: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: 1.0 + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: integer + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + TodoResponse: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: + - data + type: object + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: + data: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: null + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + Error: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: object + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: + error: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: + - code + - message + type: object + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: + code: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + message: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + details: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: array + not: null + allOf: null + oneOf: null + anyOf: null + items: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: + - field + - message + type: object + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: + field: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + message: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + responses: null + parameters: + TodoId: + name: todoId + in: path + required: true + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: uuid + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + description: null + example: null + examples: null + Status: + name: status + in: query + required: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + description: null + example: null + examples: null + Limit: + name: limit + in: query + required: null + schema: + title: null + multipleOf: null + maximum: 100.0 + exclusiveMaximum: null + minimum: 1.0 + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: integer + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: 50 + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + description: null + example: null + examples: null + SortBy: + name: sortBy + in: query + required: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: createdAt + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + description: null + example: null + examples: null + Offset: + name: offset + in: query + required: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: 0.0 + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: integer + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: 0 + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + description: null + example: null + examples: null + UserId: + name: userId + in: query + required: true + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: null + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + description: null + example: null + examples: null + SortOrder: + name: sortOrder + in: query + required: null + schema: + title: null + multipleOf: null + maximum: null + exclusiveMaximum: null + minimum: null + exclusiveMinimum: null + maxLength: null + minLength: null + pattern: null + maxItems: null + minItems: null + uniqueItems: null + maxProperties: null + minProperties: null + required: null + type: string + not: null + allOf: null + oneOf: null + anyOf: null + items: null + properties: null + additionalProperties: null + description: null + format: null + default: desc + nullable: null + discriminator: null + readOnly: null + writeOnly: null + xml: null + example: null + deprecated: null + description: null + example: null + examples: null + examples: null + requestBodies: null + headers: null + securitySchemes: + bearerAuth: + type: http + description: null + name: null + in: null + scheme: bearer + bearerFormat: JWT + flows: null + openIdConnectUrl: null +servers: +- url: /api/v1 + description: Base API path diff --git a/fooschema.yml b/fooschema.yml new file mode 100644 index 0000000..c49a3a4 --- /dev/null +++ b/fooschema.yml @@ -0,0 +1,552 @@ +$defs: + Components: + properties: + examples: + additionalProperties: + $ref: '#/$defs/Example' + type: + - object + - 'null' + headers: + additionalProperties: + $ref: '#/$defs/Header' + type: + - object + - 'null' + parameters: + additionalProperties: + $ref: '#/$defs/Parameter' + type: + - object + - 'null' + requestBodies: + additionalProperties: + $ref: '#/$defs/RequestBody' + type: + - object + - 'null' + responses: + additionalProperties: + $ref: '#/$defs/Response' + type: + - object + - 'null' + schemas: + additionalProperties: + $ref: '#/$defs/Schema' + type: + - object + - 'null' + securitySchemes: + additionalProperties: + $ref: '#/$defs/SecurityScheme' + type: + - object + - 'null' + type: object + Discriminator: + properties: + mapping: + additionalProperties: + type: string + type: + - object + - 'null' + propertyName: + type: + - string + - 'null' + type: object + Example: + properties: + description: + type: + - string + - 'null' + externalValue: + type: + - string + - 'null' + summary: + type: + - string + - 'null' + value: true + type: object + Header: + properties: + description: + type: + - string + - 'null' + example: true + schema: + anyOf: + - $ref: '#/$defs/Schema' + - type: 'null' + type: object + Info: + properties: + description: + type: + - string + - 'null' + title: + type: + - string + - 'null' + version: + type: + - string + - 'null' + type: object + MediaType: + properties: + example: true + examples: + additionalProperties: + $ref: '#/$defs/Example' + type: + - object + - 'null' + schema: + anyOf: + - $ref: '#/$defs/Schema' + - type: 'null' + type: object + OAuthFlow: + properties: + authorizationUrl: + type: + - string + - 'null' + refreshUrl: + type: + - string + - 'null' + scopes: + additionalProperties: + type: string + type: + - object + - 'null' + tokenUrl: + type: + - string + - 'null' + type: object + OAuthFlows: + properties: + authorizationCode: + anyOf: + - $ref: '#/$defs/OAuthFlow' + - type: 'null' + clientCredentials: + anyOf: + - $ref: '#/$defs/OAuthFlow' + - type: 'null' + implicit: + anyOf: + - $ref: '#/$defs/OAuthFlow' + - type: 'null' + password: + anyOf: + - $ref: '#/$defs/OAuthFlow' + - type: 'null' + type: object + Operation: + properties: + description: + type: + - string + - 'null' + operationId: + type: + - string + - 'null' + parameters: + items: + $ref: '#/$defs/Parameter' + type: + - array + - 'null' + requestBody: + anyOf: + - $ref: '#/$defs/RequestBody' + - type: 'null' + responses: + anyOf: + - $ref: '#/$defs/Responses' + - type: 'null' + summary: + type: + - string + - 'null' + tags: + items: + type: string + type: + - array + - 'null' + type: object + Parameter: + properties: + description: + type: + - string + - 'null' + example: true + examples: + additionalProperties: + $ref: '#/$defs/Example' + type: + - object + - 'null' + in: + type: + - string + - 'null' + name: + type: + - string + - 'null' + required: + type: + - boolean + - 'null' + schema: + anyOf: + - $ref: '#/$defs/Schema' + - type: 'null' + type: object + PathItem: + properties: + delete: + anyOf: + - $ref: '#/$defs/Operation' + - type: 'null' + get: + anyOf: + - $ref: '#/$defs/Operation' + - type: 'null' + head: + anyOf: + - $ref: '#/$defs/Operation' + - type: 'null' + options: + anyOf: + - $ref: '#/$defs/Operation' + - type: 'null' + patch: + anyOf: + - $ref: '#/$defs/Operation' + - type: 'null' + post: + anyOf: + - $ref: '#/$defs/Operation' + - type: 'null' + put: + anyOf: + - $ref: '#/$defs/Operation' + - type: 'null' + trace: + anyOf: + - $ref: '#/$defs/Operation' + - type: 'null' + type: object + RequestBody: + properties: + content: + additionalProperties: + $ref: '#/$defs/MediaType' + type: + - object + - 'null' + description: + type: + - string + - 'null' + required: + type: + - boolean + - 'null' + type: object + Response: + properties: + content: + additionalProperties: + $ref: '#/$defs/MediaType' + type: + - object + - 'null' + description: + type: + - string + - 'null' + headers: + additionalProperties: + $ref: '#/$defs/Header' + type: + - object + - 'null' + type: object + Responses: + additionalProperties: + $ref: '#/$defs/Response' + properties: + default: + anyOf: + - $ref: '#/$defs/Response' + - type: 'null' + type: object + Schema: + properties: + additionalProperties: + anyOf: + - $ref: '#/$defs/Schema' + - type: 'null' + allOf: + items: + $ref: '#/$defs/Schema' + type: + - array + - 'null' + anyOf: + items: + $ref: '#/$defs/Schema' + type: + - array + - 'null' + default: true + deprecated: + type: + - boolean + - 'null' + description: + type: + - string + - 'null' + discriminator: + anyOf: + - $ref: '#/$defs/Discriminator' + - type: 'null' + example: true + exclusiveMaximum: + type: + - boolean + - 'null' + exclusiveMinimum: + type: + - boolean + - 'null' + format: + type: + - string + - 'null' + items: + anyOf: + - $ref: '#/$defs/Schema' + - type: 'null' + maxItems: + format: uint32 + minimum: 0 + type: + - integer + - 'null' + maxLength: + format: uint32 + minimum: 0 + type: + - integer + - 'null' + maxProperties: + format: uint32 + minimum: 0 + type: + - integer + - 'null' + maximum: + format: double + type: + - number + - 'null' + minItems: + format: uint32 + minimum: 0 + type: + - integer + - 'null' + minLength: + format: uint32 + minimum: 0 + type: + - integer + - 'null' + minProperties: + format: uint32 + minimum: 0 + type: + - integer + - 'null' + minimum: + format: double + type: + - number + - 'null' + multipleOf: + format: double + type: + - number + - 'null' + not: + anyOf: + - $ref: '#/$defs/Schema' + - type: 'null' + nullable: + type: + - boolean + - 'null' + oneOf: + items: + $ref: '#/$defs/Schema' + type: + - array + - 'null' + pattern: + type: + - string + - 'null' + properties: + additionalProperties: + $ref: '#/$defs/Schema' + type: + - object + - 'null' + readOnly: + type: + - boolean + - 'null' + required: + items: + type: string + type: + - array + - 'null' + title: + type: + - string + - 'null' + type: + type: + - string + - 'null' + uniqueItems: + type: + - boolean + - 'null' + writeOnly: + type: + - boolean + - 'null' + xml: + anyOf: + - $ref: '#/$defs/XML' + - type: 'null' + type: object + SecurityScheme: + properties: + bearerFormat: + type: + - string + - 'null' + description: + type: + - string + - 'null' + flows: + anyOf: + - $ref: '#/$defs/OAuthFlows' + - type: 'null' + in: + type: + - string + - 'null' + name: + type: + - string + - 'null' + openIdConnectUrl: + type: + - string + - 'null' + scheme: + type: + - string + - 'null' + type: + type: + - string + - 'null' + type: object + Server: + properties: + description: + type: + - string + - 'null' + url: + type: + - string + - 'null' + type: object + XML: + properties: + attribute: + type: + - boolean + - 'null' + name: + type: + - string + - 'null' + namespace: + type: + - string + - 'null' + prefix: + type: + - string + - 'null' + wrapped: + type: + - boolean + - 'null' + type: object +$schema: https://json-schema.org/draft/2020-12/schema +properties: + components: + anyOf: + - $ref: '#/$defs/Components' + - type: 'null' + info: + anyOf: + - $ref: '#/$defs/Info' + - type: 'null' + openapi: + type: + - string + - 'null' + paths: + additionalProperties: + $ref: '#/$defs/PathItem' + type: + - object + - 'null' + servers: + items: + $ref: '#/$defs/Server' + type: + - array + - 'null' +title: OpenApiSpec +type: object diff --git a/openapi.yaml b/openapi.yaml new file mode 100644 index 0000000..eb95303 --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,441 @@ +openapi: '3.0.3' +info: + title: Todo REST API + version: '1.0.0' + description: A RESTful API for managing todo items + +servers: + - url: /api/v1 + description: Base API path + +components: + schemas: + Todo: + type: object + properties: + id: + type: string + format: uuid + readOnly: true + title: + type: string + minLength: 1 + maxLength: 200 + description: + type: string + maxLength: 2000 + completed: + type: boolean + default: false + dueDate: + type: string + format: date-time + userId: + type: string + createdAt: + type: string + format: date-time + readOnly: true + updatedAt: + type: string + format: date-time + readOnly: true + required: + - id + - title + - completed + - userId + - createdAt + - updatedAt + + TodoCreate: + type: object + properties: + title: + type: string + minLength: 1 + maxLength: 200 + description: + type: string + maxLength: 2000 + dueDate: + type: string + format: date-time + userId: + type: string + required: + - title + - userId + + TodoUpdate: + type: object + properties: + title: + type: string + minLength: 1 + maxLength: 200 + description: + type: string + maxLength: 2000 + completed: + type: boolean + dueDate: + type: string + format: date-time + minProperties: 1 + + TodoList: + type: object + properties: + data: + type: string +# items: +# $ref: '#/components/schemas/Todo' + metadata: + type: string +# properties: +# total: +# type: integer +# minimum: 0 +# limit: +# type: integer +# minimum: 1 +# offset: +# type: integer +# minimum: 0 +# required: +# - total +# - limit +# - offset + required: + - data + - metadata + + TodoResponse: + type: object + properties: + data: + type: string +# $ref: '#/components/schemas/Todo' + required: + - data + + Error: + type: object + properties: + error: + type: string +# properties: +# code: +# type: string +# enum: +# - VALIDATION_ERROR +# - UNAUTHORIZED +# - FORBIDDEN +# - NOT_FOUND +# - RATE_LIMIT_EXCEEDED +# - INTERNAL_ERROR +# message: +# type: string +# details: +# type: array +# items: +# type: object +# properties: +# field: +# type: string +# message: +# type: string +# required: +# - field +# - message +# required: +# - code +# - message + + parameters: + TodoId: + name: todoId + in: path + required: true + schema: + type: string + format: uuid + UserId: + name: userId + in: query + required: true + schema: + type: string + Status: + name: status + in: query + schema: + type: string + enum: [active, completed] + Limit: + name: limit + in: query + schema: + type: integer + minimum: 1 + maximum: 100 + default: 50 + Offset: + name: offset + in: query + schema: + type: integer + minimum: 0 + default: 0 + SortBy: + name: sortBy + in: query + schema: + type: string + enum: [createdAt, dueDate] + default: createdAt + SortOrder: + name: sortOrder + in: query + schema: + type: string + enum: [asc, desc] + default: desc + + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + +security: + - bearerAuth: [] + +paths: + /todos: + get: + summary: List todos + parameters: + - $ref: '#/components/parameters/UserId' + - $ref: '#/components/parameters/Status' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/SortBy' + - $ref: '#/components/parameters/SortOrder' + responses: + '200': + description: Successfully retrieved todos + headers: + ETag: + schema: + type: string + Last-Modified: + schema: + type: string + X-Request-ID: + schema: + type: string + X-RateLimit-Limit: + schema: + type: integer + X-RateLimit-Remaining: + schema: + type: integer + X-RateLimit-Reset: + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/TodoList' + '400': + description: Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: Too many requests + headers: + Retry-After: + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + post: + summary: Create a new todo + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TodoCreate' + responses: + '201': + description: Todo created successfully + headers: + Location: + schema: + type: string + format: uri + ETag: + schema: + type: string + X-Request-ID: + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/TodoResponse' + '400': + description: Invalid input + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /todos/{todoId}: + parameters: + - $ref: '#/components/parameters/TodoId' + + get: + summary: Get a specific todo + responses: + '200': + description: Successfully retrieved todo + headers: + ETag: + schema: + type: string + Last-Modified: + schema: + type: string + X-Request-ID: + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/TodoResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Todo not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + patch: + summary: Update a todo + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TodoUpdate' + responses: + '200': + description: Todo updated successfully + headers: + ETag: + schema: + type: string + X-Request-ID: + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/TodoResponse' + '400': + description: Invalid input + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Todo not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + delete: + summary: Delete a todo + responses: + '204': + description: Todo deleted successfully + headers: + X-Request-ID: + schema: + type: string + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Todo not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' diff --git a/src/config/config.rs b/src/config/config.rs new file mode 100644 index 0000000..34e53bb --- /dev/null +++ b/src/config/config.rs @@ -0,0 +1,60 @@ +use crate::config::wit_types::WitType; + +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct Config { + pub package: String, + pub interfaces: Vec, + pub world: World, +} + +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct World { + pub name: String, + pub uses: Vec, + pub imports: Vec, + pub exports: Vec, +} + +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct Interface { + pub name: String, + pub records: Vec, + pub uses: Vec, + pub functions: Vec, +} + +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct Record { + pub name: String, + pub fields: Vec, +} +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct UseStatement { + pub name: String, + pub items: Vec, +} + +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct Function { + pub name: String, + pub parameters: Vec, + pub return_type: ReturnTy, +} + +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct ReturnTy { + pub return_type: String, + pub error_type: String, +} + +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct Parameter { + pub name: String, + pub parameter_type: String, +} + +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct Field { + pub name: String, + pub field_type: WitType, +} diff --git a/src/config/mod.rs b/src/config/mod.rs new file mode 100644 index 0000000..a56f658 --- /dev/null +++ b/src/config/mod.rs @@ -0,0 +1,3 @@ +pub mod config; +pub mod wit_types; +pub mod to_wit; \ No newline at end of file diff --git a/src/config/to_wit.rs b/src/config/to_wit.rs new file mode 100644 index 0000000..68c3fd6 --- /dev/null +++ b/src/config/to_wit.rs @@ -0,0 +1,280 @@ +use crate::config::config::{Config, Field, Function, Interface, Parameter, Record, ReturnTy, UseStatement, World}; +use crate::config::wit_types::WitType; +use convert_case::{Case, Casing}; +use std::collections::HashSet; + +pub trait ToWit { + fn to_wit(&self) -> String; +} + +lazy_static::lazy_static! { + static ref RESERVED_WORDS: HashSet<&'static str> = { + let mut set = HashSet::new(); + set.insert("type"); + set.insert("record"); + set.insert("interface"); + set.insert("world"); + set.insert("use"); + set.insert("import"); + set.insert("export"); + // Add more reserved words if necessary + set + }; +} + +/// Generate a WIT-compatible name by applying kebab-case, truncation, and reserved word handling. +fn generate_wit_name(name: &str) -> String { + let kebab_case = name.to_case(Case::Kebab); + + // Prefix reserved words with % + let mut final_name = if RESERVED_WORDS.contains(kebab_case.as_str()) { + format!("%{}", kebab_case) + } else { + kebab_case + }; + + // Truncate to 64 characters + if final_name.len() > 64 { + final_name.truncate(64); + } + + final_name +} + +impl ToWit for Config { + fn to_wit(&self) -> String { + let package = format!("package {};\n", generate_wit_name(&self.package)); + let world = self.world.to_wit(); + let interfaces = self + .interfaces + .iter() + .map(|interface| interface.to_wit()) + .collect::>() + .join("\n\n"); + + format!("{}\n{}\n{}", package, interfaces, world) + } +} + +impl ToWit for World { + fn to_wit(&self) -> String { + if self == &World::default() { + return String::new(); + } + + let uses = self + .uses + .iter() + .map(|use_statement| use_statement.to_wit()) + .collect::>() + .join("\n"); + + let imports = self + .imports + .iter() + .map(|interface| format!("import {};", generate_wit_name(&interface.name))) + .collect::>() + .join("\n"); + + let exports = self + .exports + .iter() + .map(|interface| format!("export {};", generate_wit_name(&interface.name))) + .collect::>() + .join("\n"); + + format!( + "world {} {{\n{}\n{}\n{}\n}}", + generate_wit_name(&self.name), + uses, + imports, + exports + ) + } +} + +impl ToWit for Interface { + fn to_wit(&self) -> String { + let uses = self + .uses + .iter() + .map(|use_statement| use_statement.to_wit()) + .collect::>() + .join("\n "); + + let records = self + .records + .iter() + .map(|record| record.to_wit()) + .collect::>() + .join("\n "); + + let functions = self + .functions + .iter() + .map(|function| function.to_wit()) + .collect::>() + .join("\n "); + + format!( + "interface {} {{\n {}\n {}\n {}\n}}", + generate_wit_name(&self.name), + uses, + records, + functions + ) + } +} + +impl ToWit for Record { + fn to_wit(&self) -> String { + let fields = self + .fields + .iter() + .map(|field| field.to_wit()) + .collect::>() + .join(", "); + + format!("record {} {{ {} }}", generate_wit_name(&self.name), fields) + } +} + +impl ToWit for Field { + fn to_wit(&self) -> String { + format!( + "{}: {}", + generate_wit_name(&self.name), + self.field_type.to_wit() + ) + } +} + + +impl ToWit for Function { + fn to_wit(&self) -> String { + let params = self + .parameters + .iter() + .map(|param| param.to_wit()) + .collect::>() + .join(", "); + + let return_type = if self.return_type.return_type.is_empty() { + String::new() + } else { + format!(" -> {}", self.return_type.to_wit()) + }; + + format!( + "func {}({}){}", + generate_wit_name(&self.name), + params, + return_type + ) + } +} + +impl ToWit for ReturnTy { + fn to_wit(&self) -> String { + if self.error_type.is_empty() { + self.return_type.clone() + } else { + format!( + "result<{}, {}>", + self.return_type, + self.error_type + ) + } + } +} + +impl ToWit for Parameter { + fn to_wit(&self) -> String { + format!( + "{}: {}", + generate_wit_name(&self.name), + generate_wit_name(&self.parameter_type) + ) + } +} + +impl ToWit for UseStatement { + fn to_wit(&self) -> String { + format!( + "use {}.{{{}}};", + generate_wit_name(&self.name), + self.items + .iter() + .map(|item| generate_wit_name(item)) + .collect::>() + .join(", ") + ) + } +} + +impl ToWit for WitType { + fn to_wit(&self) -> String { + match self { + WitType::Bool => "bool".to_string(), + WitType::U8 => "u8".to_string(), + WitType::U16 => "u16".to_string(), + WitType::U32 => "u32".to_string(), + WitType::U64 => "u64".to_string(), + WitType::S8 => "s8".to_string(), + WitType::S16 => "s16".to_string(), + WitType::S32 => "s32".to_string(), + WitType::S64 => "s64".to_string(), + WitType::Float32 => "float32".to_string(), + WitType::Float64 => "float64".to_string(), + WitType::Char => "char".to_string(), + WitType::String => "string".to_string(), + WitType::Option(inner) => format!("option<{}>", inner.to_wit()), + WitType::Result(ok, err) => format!("result<{}, {}>", ok.to_wit(), err.to_wit()), + WitType::List(inner) => format!("list<{}>", inner.to_wit()), + WitType::Tuple(elements) => format!( + "tuple<{}>", + elements.iter().map(|e| e.to_wit()).collect::>().join(", ") + ), + WitType::Record(fields) => format!( + "{{ {} }}", + fields + .iter() + .map(|(name, ty)| format!("{}: {}", generate_wit_name(name), ty)) + .collect::>() + .join(", ") + ), + WitType::Variant(variants) => format!( + "variant {{ {} }}", + variants + .iter() + .map(|(name, ty)| { + if let Some(ty) = ty { + format!("{}: {}", generate_wit_name(name), ty.to_wit()) + } else { + generate_wit_name(name) + } + }) + .collect::>() + .join(", ") + ), + WitType::Enum(variants) => format!( + "enum {{ {} }}", + variants + .iter() + .map(|variant| generate_wit_name(variant)) + .collect::>() + .join(", ") + ), + WitType::Flags(flags) => format!( + "flags {{ {} }}", + flags + .iter() + .map(|flag| generate_wit_name(flag)) + .collect::>() + .join(", ") + ), + WitType::Handle(name) => format!("handle<{}>", generate_wit_name(name)), + WitType::TypeAlias(name, inner) => format!("type {} = {}", generate_wit_name(name), inner.to_wit()), + } + } +} diff --git a/src/config/wit_types.rs b/src/config/wit_types.rs new file mode 100644 index 0000000..86cf23e --- /dev/null +++ b/src/config/wit_types.rs @@ -0,0 +1,183 @@ +use tailcall_valid::{Valid, Validator}; +use crate::config::to_wit::ToWit; + +use crate::ser::{OpenApiSpec, Schema}; + +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub enum WitType { + // Primitive Types + Bool, + U8, + U16, + U32, + U64, + S8, + S16, + S32, + S64, + Float32, + Float64, + Char, + #[default] // TODO: maybe drop the default + String, + + // Compound Types + Option(Box), // Option + Result(Box, Box), // Result + List(Box), // List + Tuple(Vec), // (T1, T2, ...) + + // Custom Types + Record(Vec<(String, String)>), // Record { field_name: Type } + Variant(Vec<(String, Option)>), // Variant { name: Option } + Enum(Vec), // Enum { name1, name2, ... } + Flags(Vec), // Flags { flag1, flag2, ... } + + // Special Types + Handle(String), // Handle + TypeAlias(String, Box), // TypeAlias { alias_name, type } +} + +impl WitType { + pub fn from_schema( + schema: &Schema, + openapi: &OpenApiSpec, + ) -> Valid { + if let Some(reference) = &schema.ref_ { + return Valid::from_option( + openapi.resolve_ref(reference), + anyhow::anyhow!("Failed to resolve reference: {}", reference), + ) + .and_then(|resolved_schema| WitType::from_schema(resolved_schema, openapi)); + } + + Valid::from_option(schema.type_.as_ref(), anyhow::anyhow!("SchemaType is required")).and_then(|ty| { + match ty.as_str() { + "bool" | "boolean" => Valid::succeed(WitType::Bool), + "integer" => Valid::succeed(WitType::S32), + "number" => Valid::succeed(WitType::Float64), + "string" => Valid::succeed(WitType::String), + "array" => { + Valid::from_option(schema.items.as_ref(), anyhow::anyhow!("Items are required")) + .and_then(|items| WitType::from_schema(items, openapi)) + .map(|items_ty| WitType::List(Box::new(items_ty))) + } + "object" => { + Valid::from_option(schema.properties.as_ref(), anyhow::anyhow!("Properties are required")) + .and_then(|properties| { + Valid::from_iter(properties.iter(), |(name, schema)| { + Valid::from(WitType::from_schema(schema, openapi)).map(|ty| (name.clone(), ty.to_wit())) + }) + } + ) + .map(|fields| WitType::Record(fields)) + } + _ => Valid::fail(anyhow::anyhow!("Unknown type: {}", ty)), + } + }) + } +} + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + use crate::ser::Components; + use super::*; + + #[test] + fn test_ref_resolution() { + let mut schemas = HashMap::new(); + schemas.insert( + "ReferencedSchema".to_string(), + Schema { + type_: Some("string".to_string()), + ..Default::default() + }, + ); + + let openapi = OpenApiSpec { + components: Some(Components { + schemas: Some(schemas), + ..Default::default() + }), + ..Default::default() + }; + + let schema = Schema { + ref_: Some("#/components/schemas/ReferencedSchema".to_string()), + ..Default::default() + }; + + let result = WitType::from_schema(&schema, &openapi).to_result().unwrap(); + assert_eq!(result, WitType::String); + } + + #[test] + fn test_array_with_ref() { + let mut schemas = HashMap::new(); + schemas.insert( + "ReferencedSchema".to_string(), + Schema { + type_: Some("string".to_string()), + ..Default::default() + }, + ); + + let openapi = OpenApiSpec { + components: Some(Components { + schemas: Some(schemas), + ..Default::default() + }), + ..Default::default() + }; + + let schema = Schema { + type_: Some("array".to_string()), + items: Some(Box::new(Schema { + ref_: Some("#/components/schemas/ReferencedSchema".to_string()), + ..Default::default() + })), + ..Default::default() + }; + + let result = WitType::from_schema(&schema, &openapi).to_result().unwrap(); + assert_eq!(result, WitType::List(Box::new(WitType::String))); + } + + #[test] + fn test_object_with_properties() { + let properties = vec![ + ( + "id".to_string(), + Schema { + type_: Some("integer".to_string()), + ..Default::default() + }, + ), + ( + "name".to_string(), + Schema { + type_: Some("string".to_string()), + ..Default::default() + }, + ), + ]; + + let schema = Schema { + type_: Some("object".to_string()), + properties: Some(properties.into_iter().collect()), + ..Default::default() + }; + + let openapi = OpenApiSpec::default(); + + let result = WitType::from_schema(&schema, &openapi).to_result().unwrap(); + assert_eq!( + result, + WitType::Record(vec![ + ("id".to_string(), WitType::S32.to_wit()), + ("name".to_string(), WitType::String.to_wit()), + ]) + ); + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..87b8aac --- /dev/null +++ b/src/main.rs @@ -0,0 +1,134 @@ +mod value; +mod proto; +mod ser; +mod config; + +use serde_json::{Map, Value}; +use anyhow::{Result, bail}; +use convert_case::{Casing, Case}; +use crate::value::value; + +#[derive(Debug, Clone)] +pub struct WIPValue(Value); + +impl WIPValue { + pub fn to_wip(&self) -> Result { + let value = &self.0; + match value { + Value::Object(map) => { + let mut wip = String::new(); + wip.push_str("package api:todos@1.0.0;\n\n"); + + if let Some(components) = map.get("components") { + if let Some(schemas) = components.get("schemas") { + if let Value::Object(schemas_map) = schemas { + wip.push_str("interface types {\n"); + for (name, schema) in schemas_map { + let record = Self::process_schema(name, schema, schemas_map)?; + wip.push_str(&record); + } + wip.push_str("}\n\n"); + } + } + } + + if let Some(paths) = map.get("paths") { + if let Value::Object(paths_map) = paths { + for (path, methods) in paths_map { + let interfaces = Self::process_paths(path, methods)?; + wip.push_str(&interfaces); + } + } + } + + wip.push_str("world todos-api {\n"); + wip.push_str(" export todos-collection;\n"); + wip.push_str(" export todos-resource;\n"); + wip.push_str("}\n"); + + Ok(wip) + } + _ => bail!("Root JSON value must be an object."), + } + } + + fn process_schema(name: &str, schema: &Value, schemas_map: &Map) -> Result { + if let Value::Object(schema_map) = schema { + let mut record = format!(" record {} {{\n", name.from_case(Case::Camel).to_case(Case::Kebab)); + if let Some(properties) = schema_map.get("properties") { + if let Value::Object(properties_map) = properties { + for (field, field_schema) in properties_map { + let field_type = match field_schema.get("$ref") { + Some(Value::String(ref_path)) => { + let referenced_name = ref_path.split('/').last().unwrap(); + referenced_name.from_case(Case::Camel).to_case(Case::Kebab) + } + _ => Self::json_to_wip_type(field_schema)?.to_string(), + }; + record.push_str(&format!(" {}: {},\n", field.replace('-', "_"), field_type)); + } + } + } + record.push_str(" }\n"); + return Ok(record); + } + bail!("Invalid schema format.") + } + + fn process_paths(path: &str, methods: &Value) -> Result { + let mut interfaces = String::new(); + if let Value::Object(methods_map) = methods { + for (method, details) in methods_map { + let interface_name = format!("{}-{}", path.split('/').filter(|v| v.is_empty()).collect::>().join("-"), method).from_case(Case::Camel).to_case(Case::Kebab); + interfaces.push_str(&format!("interface {} {{\n", interface_name)); + + if let Value::Object(details_map) = details { + if let Some(parameters) = details_map.get("parameters") { + if let Value::Array(params_array) = parameters { + for param in params_array { + if let Value::Object(param_map) = param { + let param_name = param_map.get("name").and_then(Value::as_str).unwrap_or("unknown"); + let param_type = param_map.get("schema").map(|schema| Self::json_to_wip_type(schema).unwrap_or("unknown")).unwrap_or("unknown"); + interfaces.push_str(&format!(" {}: {},\n", param_name.replace('-', "_"), param_type)); + } + } + } + } + } + + interfaces.push_str("}\n\n"); + } + } + Ok(interfaces) + } + + fn json_to_wip_type(value: &Value) -> Result<&'static str> { + match value { + Value::String(_) => Ok("string"), + Value::Number(num) => { + if num.is_i64() { + Ok("s64") + } else if num.is_u64() { + Ok("u64") + } else { + Ok("float64") + } + } + Value::Bool(_) => Ok("bool"), + Value::Array(_) => Ok("list"), + Value::Object(_) => Ok("record"), + Value::Null => Ok("option"), + } + } +} + +// Example usage +fn main() -> Result<()> { + let json_schema = value(); + + let wip_value = WIPValue(json_schema); + let wip_string = wip_value.to_wip()?; + println!("{}", wip_string); + + Ok(()) +} diff --git a/src/proto.rs b/src/proto.rs new file mode 100644 index 0000000..317ad4b --- /dev/null +++ b/src/proto.rs @@ -0,0 +1,84 @@ +use anyhow::{anyhow, Error}; +use tailcall_valid::{Valid, Validator}; + +use crate::config::config::{Config, Field, Interface, Record}; +use crate::config::wit_types::WitType; +use crate::ser::OpenApiSpec; + +fn handle_types(config: Config, spec: &OpenApiSpec) -> Valid { + Valid::succeed(config).and_then(|mut config: Config| { + Valid::from_option(spec.components.as_ref(), anyhow!("Components are required")) + .and_then(|v| Valid::from_option(v.schemas.as_ref(), anyhow!("Schemas are required"))) + .and_then(|schemas| { + Valid::from_iter(schemas.iter(), |(record_name, v)| { + Valid::from_option(v.type_.as_ref(), anyhow!("Type is required")) + .and_then(|type_| { + Valid::from_option(v.properties.as_ref(), anyhow!("Properties are required")) + .and_then(|a| { + Valid::from_iter(a, |(field_name, v)| { + Valid::from(WitType::from_schema(v, spec)) + .and_then(|wit_type| { + let field = Field { + name: field_name.clone(), + field_type: wit_type, + }; + Valid::succeed(field) + }) + }) + }) + .and_then(|fields| { + let record = Record { + name: record_name.clone(), + fields, + }; + Valid::succeed(record) + }) + }) + }).and_then(|records| { + let interface = Interface { + name: "types".to_string(), + records, + ..Default::default() + }; + config.interfaces.push(interface); + Valid::succeed(()) + }) + }).and_then(|_| Valid::succeed(config)) + }) +} + +fn to_config(spec: OpenApiSpec) -> Valid { + Valid::succeed(Config::default()) + .and_then(|config| handle_types(config, &spec)) +} + +#[cfg(test)] +mod t { + use tailcall_valid::Validator; + use wit_parser::Resolve; + + use crate::proto::to_config; + use crate::ser::OpenApiSpec; + use crate::config::to_wit::ToWit; + + #[test] + fn tp() { + let path = concat!(env!("CARGO_MANIFEST_DIR"), "/openapi.yaml"); + let content = std::fs::read_to_string(path).unwrap(); + + let y: OpenApiSpec = serde_yaml::from_str(&content).unwrap(); + let mut res = to_config(y).to_result(); + match res.as_mut() { + Ok(v) => { + v.package = "api:todos@1.0.0".to_string(); + println!("{}", v.to_wit()); + let mut resolve = Resolve::new(); + resolve.push_str("foox.wit", &v.to_wit()).expect("TODO: panic message`"); + println!("{:#?}", resolve); + } + Err(e) => { + println!("err: {:?}", e); + } + } + } +} diff --git a/src/ser.rs b/src/ser.rs new file mode 100644 index 0000000..ea0416e --- /dev/null +++ b/src/ser.rs @@ -0,0 +1,231 @@ +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use schemars::JsonSchema; + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct OpenApiSpec { + pub openapi: Option, + pub info: Option, + pub paths: Option>, + pub components: Option, + pub servers: Option>, +} + +impl OpenApiSpec { + pub fn resolve_ref(&self, reference: &str) -> Option<&Schema> { + if let Some(components) = &self.components { + if reference.starts_with("#/components/schemas/") { + let name = reference.trim_start_matches("#/components/schemas/"); + return components.schemas.as_ref()?.get(name); + } + } + None + } +} + + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct Info { + pub title: Option, + pub description: Option, + pub version: Option, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct Server { + pub url: Option, + pub description: Option, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct PathItem { + pub get: Option, + pub post: Option, + pub put: Option, + pub delete: Option, + pub patch: Option, + pub options: Option, + pub head: Option, + pub trace: Option, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct Operation { + pub tags: Option>, + pub summary: Option, + pub description: Option, + pub operation_id: Option, + pub parameters: Option>, + pub request_body: Option, + pub responses: Option, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct Parameter { + pub name: Option, + #[serde(rename = "in")] // in is a reserved keyword in Rust + pub in_: Option, + pub required: Option, + pub schema: Option, + pub description: Option, + pub example: Option, + pub examples: Option>, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct RequestBody { + pub content: Option>, + pub description: Option, + pub required: Option, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct MediaType { + pub schema: Option, + pub example: Option, + pub examples: Option>, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct Responses { + #[serde(flatten)] + pub responses: Option>, + pub default: Option, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct Response { + pub description: Option, + pub content: Option>, + pub headers: Option>, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct Header { + pub description: Option, + pub schema: Option, + pub example: Option, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct Components { + pub schemas: Option>, + pub responses: Option>, + pub parameters: Option>, + pub examples: Option>, + pub request_bodies: Option>, + pub headers: Option>, + pub security_schemes: Option>, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct Example { + pub summary: Option, + pub description: Option, + pub value: Option, + pub external_value: Option, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct Schema { + #[serde(rename = "$ref")] + pub ref_: Option, + pub title: Option, + pub multiple_of: Option, + pub maximum: Option, + pub exclusive_maximum: Option, + pub minimum: Option, + pub exclusive_minimum: Option, + pub max_length: Option, + pub min_length: Option, + pub pattern: Option, + pub max_items: Option, + pub min_items: Option, + pub unique_items: Option, + pub max_properties: Option, + pub min_properties: Option, + pub required: Option>, + #[serde(rename = "type")] + pub type_: Option, + pub not: Option>, + pub all_of: Option>, + pub one_of: Option>, + pub any_of: Option>, + pub items: Option>, + pub properties: Option>, + pub additional_properties: Option>, + pub description: Option, + pub format: Option, + pub default: Option, + pub nullable: Option, + pub discriminator: Option, + pub read_only: Option, + pub write_only: Option, + pub xml: Option, + pub example: Option, + pub deprecated: Option, +} + + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct Discriminator { + pub property_name: Option, + pub mapping: Option>, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct SecurityScheme { + #[serde(rename = "type")] + pub type_: Option, + pub description: Option, + pub name: Option, + pub in_: Option, // `in` is renamed to `in_` in Rust + pub scheme: Option, + pub bearer_format: Option, + pub flows: Option, + pub open_id_connect_url: Option, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct OAuthFlows { + pub implicit: Option, + pub password: Option, + pub client_credentials: Option, + pub authorization_code: Option, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct OAuthFlow { + pub authorization_url: Option, + pub token_url: Option, + pub refresh_url: Option, + pub scopes: Option>, +} + +#[derive(Serialize, Clone, Deserialize, Debug, JsonSchema, Default)] +#[serde(rename_all = "camelCase")] +pub struct XML { + pub name: Option, + pub namespace: Option, + pub prefix: Option, + pub attribute: Option, + pub wrapped: Option, +} diff --git a/src/value.rs b/src/value.rs new file mode 100644 index 0000000..a1d7e90 --- /dev/null +++ b/src/value.rs @@ -0,0 +1,6 @@ +use serde_json::Value; + +pub fn value() -> Value { + let schema = std::fs::read_to_string("openapi.yaml").unwrap(); + serde_yaml::from_str::(&schema).unwrap() +} diff --git a/test.md b/test.md new file mode 100644 index 0000000..f59d87d --- /dev/null +++ b/test.md @@ -0,0 +1,536 @@ +## Example for OpenAPI + + +```yaml +openapi: '3.0.3' +info: + title: Todo REST API + version: '1.0.0' + description: A RESTful API for managing todo items + +servers: + - url: /api/v1 + description: Base API path + +components: + schemas: + Todo: + type: object + properties: + id: + type: string + format: uuid + readOnly: true + title: + type: string + minLength: 1 + maxLength: 200 + description: + type: string + maxLength: 2000 + completed: + type: boolean + default: false + dueDate: + type: string + format: date-time + userId: + type: string + createdAt: + type: string + format: date-time + readOnly: true + updatedAt: + type: string + format: date-time + readOnly: true + required: + - id + - title + - completed + - userId + - createdAt + - updatedAt + + TodoCreate: + type: object + properties: + title: + type: string + minLength: 1 + maxLength: 200 + description: + type: string + maxLength: 2000 + dueDate: + type: string + format: date-time + userId: + type: string + required: + - title + - userId + + TodoUpdate: + type: object + properties: + title: + type: string + minLength: 1 + maxLength: 200 + description: + type: string + maxLength: 2000 + completed: + type: boolean + dueDate: + type: string + format: date-time + minProperties: 1 + + TodoList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Todo' + metadata: + type: object + properties: + total: + type: integer + minimum: 0 + limit: + type: integer + minimum: 1 + offset: + type: integer + minimum: 0 + required: + - total + - limit + - offset + required: + - data + - metadata + + TodoResponse: + type: object + properties: + data: + $ref: '#/components/schemas/Todo' + required: + - data + + Error: + type: object + properties: + error: + type: object + properties: + code: + type: string + enum: + - VALIDATION_ERROR + - UNAUTHORIZED + - FORBIDDEN + - NOT_FOUND + - RATE_LIMIT_EXCEEDED + - INTERNAL_ERROR + message: + type: string + details: + type: array + items: + type: object + properties: + field: + type: string + message: + type: string + required: + - field + - message + required: + - code + - message + + parameters: + TodoId: + name: todoId + in: path + required: true + schema: + type: string + format: uuid + UserId: + name: userId + in: query + required: true + schema: + type: string + Status: + name: status + in: query + schema: + type: string + enum: [active, completed] + Limit: + name: limit + in: query + schema: + type: integer + minimum: 1 + maximum: 100 + default: 50 + Offset: + name: offset + in: query + schema: + type: integer + minimum: 0 + default: 0 + SortBy: + name: sortBy + in: query + schema: + type: string + enum: [createdAt, dueDate] + default: createdAt + SortOrder: + name: sortOrder + in: query + schema: + type: string + enum: [asc, desc] + default: desc + + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + +security: + - bearerAuth: [] + +paths: + /todos: + get: + summary: List todos + parameters: + - $ref: '#/components/parameters/UserId' + - $ref: '#/components/parameters/Status' + - $ref: '#/components/parameters/Limit' + - $ref: '#/components/parameters/Offset' + - $ref: '#/components/parameters/SortBy' + - $ref: '#/components/parameters/SortOrder' + responses: + '200': + description: Successfully retrieved todos + headers: + ETag: + schema: + type: string + Last-Modified: + schema: + type: string + X-Request-ID: + schema: + type: string + X-RateLimit-Limit: + schema: + type: integer + X-RateLimit-Remaining: + schema: + type: integer + X-RateLimit-Reset: + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/TodoList' + '400': + description: Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + description: Too many requests + headers: + Retry-After: + schema: + type: integer + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + post: + summary: Create a new todo + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TodoCreate' + responses: + '201': + description: Todo created successfully + headers: + Location: + schema: + type: string + format: uri + ETag: + schema: + type: string + X-Request-ID: + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/TodoResponse' + '400': + description: Invalid input + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /todos/{todoId}: + parameters: + - $ref: '#/components/parameters/TodoId' + + get: + summary: Get a specific todo + responses: + '200': + description: Successfully retrieved todo + headers: + ETag: + schema: + type: string + Last-Modified: + schema: + type: string + X-Request-ID: + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/TodoResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Todo not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + patch: + summary: Update a todo + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TodoUpdate' + responses: + '200': + description: Todo updated successfully + headers: + ETag: + schema: + type: string + X-Request-ID: + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/TodoResponse' + '400': + description: Invalid input + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Todo not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + delete: + summary: Delete a todo + responses: + '204': + description: Todo deleted successfully + headers: + X-Request-ID: + schema: + type: string + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Todo not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' +``` + +```wit +package api:todos@1.0.0; + +// Common types used across the API +interface types { + // Authentication types derived from OpenAPI security schemes + record bearer-token { + token: string, + } + + // Core resource type + record todo { + id: string, + title: string, + description: option, + completed: bool, + due-date: option, + user-id: string, + created-at: string, + updated-at: string, + } + + variant error { + unauthorized, + not-found, + validation-error(list), + rate-limited { retry-after: u32 }, + server-error, + } +} + +interface todos-collection { + use types.{todo, bearer-token, error}; + + // Request/response types with domain-appropriate fields + record list-request { + auth: bearer-token, + user-id: string, + status: option, + limit: option, + %offset: option, + } + + record list-response { + items: list, + total: u32, + limit: u32, + %offset: u32, + version: string, // From ETag + last-updated: option, // From Last-Modified + } + + record create-request { + auth: bearer-token, + title: string, + description: option, + due-date: option, + user-id: string, + } + + // Note: Response includes versioning info directly in return type + list: func(request: list-request) -> result; + + create: func(request: create-request) -> result; +} + +interface todos-resource { + use types.{todo, bearer-token, error}; + + record update-request { + auth: bearer-token, + title: option, + description: option, + completed: option, + due-date: option, + expected-version: option, // If-Match header + } + + get: func(id: string, auth: bearer-token) -> result; + + update: func(id: string, request: update-request) -> result; + + delete: func(id: string, auth: bearer-token) -> result; +} + +world todos-api { + export todos-collection; + export todos-resource; +} +``` \ No newline at end of file