diff --git a/Cargo.lock b/Cargo.lock index 7b749c7..97b35dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,716 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "bitflags" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a" + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "cc" +version = "1.2.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "frilvault-core" version = "0.1.0" +dependencies = [ + "chrono", + "serde", + "serde_yml", + "thiserror", + "uuid", +] + +[[package]] +name = "frivault-cli" +version = "0.1.0" + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[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 = "log" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f" + +[[package]] +name = "memchr" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_yml" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd" +dependencies = [ + "indexmap", + "itoa", + "libyml", + "memchr", + "ryu", + "serde", + "version_check", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "uuid" +version = "1.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" +dependencies = [ + "getrandom", + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index ff9a47e..41c6fba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = [ +members = ["apps/frivault-cli", "crates/frilvault-core" -] \ No newline at end of file +] diff --git a/apps/frivault-cli/Cargo.toml b/apps/frivault-cli/Cargo.toml new file mode 100644 index 0000000..e1945e8 --- /dev/null +++ b/apps/frivault-cli/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "frivault-cli" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/apps/frivault-cli/src/main.rs b/apps/frivault-cli/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/apps/frivault-cli/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/crates/frilvault-core/Cargo.toml b/crates/frilvault-core/Cargo.toml index 6b9d988..95af3cc 100644 --- a/crates/frilvault-core/Cargo.toml +++ b/crates/frilvault-core/Cargo.toml @@ -4,3 +4,8 @@ version = "0.1.0" edition = "2024" [dependencies] +chrono = { version = "0.4", features = ["serde"] } +serde = { version = "1", features = ["derive"] } +serde_yml = "0.0.12" +thiserror = "2" +uuid = { version = "1", features = ["v4", "serde"] } \ No newline at end of file diff --git a/crates/frilvault-core/src/constants.rs b/crates/frilvault-core/src/constants.rs new file mode 100644 index 0000000..3620637 --- /dev/null +++ b/crates/frilvault-core/src/constants.rs @@ -0,0 +1,3 @@ +pub const VAULT_DIR_NAME: &str = ".vault"; +pub const NOTE_FILE_EXTENSION: &str = "yml"; +pub const SCHEMA_VERSION: u32 = 1; diff --git a/crates/frilvault-core/src/error/errors.rs b/crates/frilvault-core/src/error/errors.rs new file mode 100644 index 0000000..fa6bb91 --- /dev/null +++ b/crates/frilvault-core/src/error/errors.rs @@ -0,0 +1,13 @@ +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum FrilVaultError { + #[error("io error: {0}")] + Io(#[from] std::io::Error), + + #[error("yaml error: {0}")] + Yaml(#[from] serde_yml::Error), + + #[error("source file path is outside workspace root")] + SourcePathOutsideWorkspace, +} diff --git a/crates/frilvault-core/src/error/mod.rs b/crates/frilvault-core/src/error/mod.rs new file mode 100644 index 0000000..08b1ce3 --- /dev/null +++ b/crates/frilvault-core/src/error/mod.rs @@ -0,0 +1,3 @@ +mod errors; + +pub use errors::FrilVaultError; diff --git a/crates/frilvault-core/src/lib.rs b/crates/frilvault-core/src/lib.rs index b93cf3f..932d5a4 100644 --- a/crates/frilvault-core/src/lib.rs +++ b/crates/frilvault-core/src/lib.rs @@ -1,14 +1,16 @@ -pub fn add(left: u64, right: u64) -> u64 { - left + right -} +pub mod constants; +pub mod error; +pub mod note; +pub mod parser; +pub mod storage; +pub mod workspace; -#[cfg(test)] -mod tests { - use super::*; +pub use error::FrilVaultError; +pub use note::{AddNoteInput, Note, NoteFile, NoteService}; +pub use storage::YamlNoteRepository; +pub use workspace::{PathResolver, Workspace}; + +pub type FrilVaultResult = Result; - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +#[cfg(test)] +mod tests; diff --git a/crates/frilvault-core/src/note/entity.rs b/crates/frilvault-core/src/note/entity.rs new file mode 100644 index 0000000..26a541c --- /dev/null +++ b/crates/frilvault-core/src/note/entity.rs @@ -0,0 +1,90 @@ +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; +use uuid::Uuid; + +// TODO: Regex parser +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "type")] +pub enum NoteAnchor { + Line(LineAnchor), + Symbol(SymbolAnchor), +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct LineAnchor { + pub line: u32, + pub column: u32, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct SymbolAnchor { + pub name: String, + pub kind: SymbolKind, + pub signature: Option, + pub line_hint: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub enum SymbolKind { + Function, + Struct, + Enum, + Trait, + Impl, + Method, + Unknown, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct Note { + /// id + pub id: Uuid, + + /// source_file + pub source_file: PathBuf, + + /// anchor: the position where the note is anchored. it can be either line-based or symbol-based. + pub anchor: NoteAnchor, + + /// content: the content of the note. + pub content: String, + + /// created_at: the time when the note was created. + pub created_at: DateTime, + + /// updated_at: the time when the note was last updated. initially same as created_at. + pub updated_at: DateTime, +} + +#[derive(Debug, Clone)] +pub struct AddNoteInput { + /// source_file: the path to the source file where the note is located. + pub source_file: PathBuf, + + /// anchor: the position where the note is anchored. it can be either line-based or symbol-based. + pub anchor: NoteAnchor, + + /// content: the content of the note to be saved. + pub content: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] +pub struct NoteFile { + pub notes: Vec, +} + +impl Note { + pub fn new(input: AddNoteInput) -> Self { + let now = Utc::now(); + + Self { + id: Uuid::new_v4(), + source_file: input.source_file, + anchor: input.anchor, + content: input.content, + created_at: now, + updated_at: now, + } + } +} diff --git a/crates/frilvault-core/src/note/mod.rs b/crates/frilvault-core/src/note/mod.rs new file mode 100644 index 0000000..14b3159 --- /dev/null +++ b/crates/frilvault-core/src/note/mod.rs @@ -0,0 +1,5 @@ +mod entity; +mod service; + +pub use entity::*; +pub use service::*; diff --git a/crates/frilvault-core/src/note/service.rs b/crates/frilvault-core/src/note/service.rs new file mode 100644 index 0000000..302a0c1 --- /dev/null +++ b/crates/frilvault-core/src/note/service.rs @@ -0,0 +1,31 @@ +use std::path::Path; + +use crate::{ + FrilVaultResult, + note::{AddNoteInput, Note}, + storage::YamlNoteRepository, +}; + +pub struct NoteService { + repository: YamlNoteRepository, +} + +impl NoteService { + pub fn new(repository: YamlNoteRepository) -> Self { + Self { repository } + } + + pub fn add_note(&self, input: AddNoteInput) -> FrilVaultResult { + let note = Note::new(input); + + self.repository.append_note(¬e)?; + + Ok(note) + } + + pub fn list_notes(&self, source_file: impl AsRef) -> FrilVaultResult> { + let note_file = self.repository.load_by_source_file(source_file.as_ref())?; + + Ok(note_file.notes) + } +} diff --git a/crates/frilvault-core/src/parser/mod.rs b/crates/frilvault-core/src/parser/mod.rs new file mode 100644 index 0000000..0ad212a --- /dev/null +++ b/crates/frilvault-core/src/parser/mod.rs @@ -0,0 +1,5 @@ +pub mod note_parser; +pub mod yaml_parser; + +pub use note_parser::NoteParser; +pub use yaml_parser::YamlParser; diff --git a/crates/frilvault-core/src/parser/note_parser.rs b/crates/frilvault-core/src/parser/note_parser.rs new file mode 100644 index 0000000..51f58fa --- /dev/null +++ b/crates/frilvault-core/src/parser/note_parser.rs @@ -0,0 +1,8 @@ +use crate::FrilVaultResult; +use crate::note::NoteFile; + +pub trait NoteParser { + fn serialize(&self, note_file: &NoteFile) -> FrilVaultResult; + + fn deserialize(&self, content: &str) -> FrilVaultResult; +} diff --git a/crates/frilvault-core/src/parser/yaml_parser.rs b/crates/frilvault-core/src/parser/yaml_parser.rs new file mode 100644 index 0000000..4d6cdb2 --- /dev/null +++ b/crates/frilvault-core/src/parser/yaml_parser.rs @@ -0,0 +1,16 @@ +use crate::FrilVaultResult; +use crate::note::NoteFile; +use crate::parser::NoteParser; + +#[derive(Debug, Default, Clone)] +pub struct YamlParser; + +impl NoteParser for YamlParser { + fn serialize(&self, note_file: &NoteFile) -> FrilVaultResult { + Ok(serde_yml::to_string(note_file)?) + } + + fn deserialize(&self, content: &str) -> FrilVaultResult { + Ok(serde_yml::from_str(content)?) + } +} diff --git a/crates/frilvault-core/src/storage/mod.rs b/crates/frilvault-core/src/storage/mod.rs new file mode 100644 index 0000000..137a408 --- /dev/null +++ b/crates/frilvault-core/src/storage/mod.rs @@ -0,0 +1,3 @@ +mod yaml_repository; + +pub use yaml_repository::*; diff --git a/crates/frilvault-core/src/storage/yaml_repository.rs b/crates/frilvault-core/src/storage/yaml_repository.rs new file mode 100644 index 0000000..ee80dd3 --- /dev/null +++ b/crates/frilvault-core/src/storage/yaml_repository.rs @@ -0,0 +1,69 @@ +use crate::FrilVaultResult; +use crate::note::{Note, NoteFile}; +use crate::parser::{NoteParser, YamlParser}; +use crate::workspace::PathResolver; +use std::fs; +use std::path::{Path, PathBuf}; + +#[derive(Debug, Clone)] +pub struct YamlNoteRepository { + path_resolver: PathResolver, + parser: YamlParser, +} + +impl YamlNoteRepository { + // Create a YamlNoteRepository with the given PathResolver. + pub fn new(path_resolver: PathResolver) -> Self { + Self { + path_resolver, + parser: YamlParser, + } + } + + // Read the existing note file, append the new note, and save it again. + pub fn append_note(&self, note: &Note) -> FrilVaultResult<()> { + let mut note_file = self.load_by_source_file(¬e.source_file)?; + + note_file.notes.push(note.clone()); + + self.save_by_source_file(¬e.source_file, ¬e_file)?; + + Ok(()) + } + + // If the file does not exist, it returns an empty NoteFile. + pub fn load_by_source_file(&self, source_file: &Path) -> FrilVaultResult { + let note_path = self.path_resolver.resolve_note_path(source_file); + + self.load_by_note_path(note_path) + } + + pub fn save_by_source_file( + &self, + source_file: &Path, + note_file: &NoteFile, + ) -> FrilVaultResult<()> { + let note_path = self.path_resolver.resolve_note_path(source_file); + + if let Some(parent) = note_path.parent() { + fs::create_dir_all(parent)?; + } + + let yaml = self.parser.serialize(note_file)?; + + fs::write(note_path, yaml)?; + + Ok(()) + } + + fn load_by_note_path(&self, note_path: PathBuf) -> FrilVaultResult { + if !note_path.exists() { + return Ok(NoteFile::default()); + } + + let content = fs::read_to_string(note_path)?; + let note_file = self.parser.deserialize(&content)?; + + Ok(note_file) + } +} diff --git a/crates/frilvault-core/src/tests/mod.rs b/crates/frilvault-core/src/tests/mod.rs new file mode 100644 index 0000000..c836ebd --- /dev/null +++ b/crates/frilvault-core/src/tests/mod.rs @@ -0,0 +1,11 @@ +#[cfg(test)] +mod note_entity_test; + +#[cfg(test)] +mod note_resolver_test; + +#[cfg(test)] +mod note_service_test; + +#[cfg(test)] +mod yaml_parser_test; diff --git a/crates/frilvault-core/src/tests/note_entity_test.rs b/crates/frilvault-core/src/tests/note_entity_test.rs new file mode 100644 index 0000000..a666a1a --- /dev/null +++ b/crates/frilvault-core/src/tests/note_entity_test.rs @@ -0,0 +1,41 @@ +use crate::{ + AddNoteInput, + note::{LineAnchor, Note, NoteAnchor}, +}; + +#[test] +fn create_note_from_input() { + let input = AddNoteInput { + source_file: "src/main.rs".into(), + anchor: NoteAnchor::Line(LineAnchor { + line: 10, + column: 5, + }), + content: "test note".to_string(), + }; + + let note = Note::new(input); + + assert_eq!(note.content, "test note"); + + match note.anchor { + NoteAnchor::Line(anchor) => { + assert_eq!(anchor.line, 10); + assert_eq!(anchor.column, 5); + } + _ => panic!("expected line anchor"), + } +} + +#[test] +fn create_note_generates_uuid() { + let input = AddNoteInput { + source_file: "src/main.rs".into(), + anchor: NoteAnchor::Line(LineAnchor { line: 1, column: 1 }), + content: "uuid test".to_string(), + }; + + let note = Note::new(input); + + assert_ne!(note.id.to_string(), ""); +} diff --git a/crates/frilvault-core/src/tests/note_resolver_test.rs b/crates/frilvault-core/src/tests/note_resolver_test.rs new file mode 100644 index 0000000..eed9a06 --- /dev/null +++ b/crates/frilvault-core/src/tests/note_resolver_test.rs @@ -0,0 +1,21 @@ +use crate::PathResolver; + +#[test] +fn resolve_note_path_returns_vault_path() { + let resolver = PathResolver::new("/workspace"); + + let path = resolver.resolve_note_path("src/main.rs"); + + assert!(path.ends_with(".vault/src/main.rs.yml")); +} + +#[test] +fn workspace_relative_path() { + let resolver = PathResolver::new("/workspace"); + + let relative = resolver + .to_workspace_relative("/workspace/src/main.rs") + .unwrap(); + + assert_eq!(relative.to_string_lossy(), "src/main.rs"); +} diff --git a/crates/frilvault-core/src/tests/note_service_test.rs b/crates/frilvault-core/src/tests/note_service_test.rs new file mode 100644 index 0000000..4e2fa57 --- /dev/null +++ b/crates/frilvault-core/src/tests/note_service_test.rs @@ -0,0 +1,106 @@ +use crate::{ + AddNoteInput, NoteService, PathResolver, YamlNoteRepository, constants::NOTE_FILE_EXTENSION, +}; + +use std::fs; + +#[test] +fn add_note_creates_yaml_file() { + let workspace_root = + std::env::temp_dir().join(format!("frilvault-test-{}", uuid::Uuid::new_v4())); + + fs::create_dir_all(&workspace_root).unwrap(); + + let resolver = PathResolver::new(&workspace_root); + let repository = YamlNoteRepository::new(resolver); + let service = NoteService::new(repository); + + let input = AddNoteInput { + source_file: "src/main.rs".into(), + anchor: crate::note::NoteAnchor::Line(crate::note::LineAnchor { + line: 10, + column: 5, + }), + content: "여기서 스캔이 시작된다.".to_string(), + }; + + service.add_note(input).unwrap(); + + let note_path = workspace_root + .join(".vault") + .join(format!("src/main.rs.{}", NOTE_FILE_EXTENSION)); + + assert!(note_path.exists()); + + let content = fs::read_to_string(note_path).unwrap(); + + assert!(content.contains("여기서 스캔이 시작된다.")); + + fs::remove_dir_all(workspace_root).unwrap(); +} + +#[test] +fn load_notes_from_existing_yaml() { + let workspace_root = + std::env::temp_dir().join(format!("frilvault-test-{}", uuid::Uuid::new_v4())); + + fs::create_dir_all(&workspace_root).unwrap(); + + let resolver = PathResolver::new(&workspace_root); + let repository = YamlNoteRepository::new(resolver); + let service = NoteService::new(repository); + + service + .add_note(AddNoteInput { + source_file: "src/lib.rs".into(), + anchor: crate::note::NoteAnchor::Line(crate::note::LineAnchor { line: 1, column: 1 }), + content: "lib 진입점".to_string(), + }) + .unwrap(); + + let notes = service.list_notes("src/lib.rs").unwrap(); + + assert_eq!(notes.len(), 1); + assert_eq!(notes[0].content, "lib 진입점"); + + fs::remove_dir_all(workspace_root).unwrap(); +} + +#[test] +fn add_note_and_load_note() { + let workspace_root = + std::env::temp_dir().join(format!("frilvault-test-{}", uuid::Uuid::new_v4())); + + fs::create_dir_all(&workspace_root).unwrap(); + + let resolver = PathResolver::new(&workspace_root); + let repository = YamlNoteRepository::new(resolver); + let service = NoteService::new(repository); + + service + .add_note(AddNoteInput { + source_file: "src/main.rs".into(), + anchor: crate::note::NoteAnchor::Line(crate::note::LineAnchor { + line: 10, + column: 5, + }), + content: "여기서 스캔 시작".to_string(), + }) + .unwrap(); + + let notes = service.list_notes("src/main.rs").unwrap(); + + assert_eq!(notes.len(), 1); + + assert_eq!(notes[0].content, "여기서 스캔 시작"); + + match ¬es[0].anchor { + crate::note::NoteAnchor::Line(anchor) => { + assert_eq!(anchor.line, 10); + assert_eq!(anchor.column, 5); + } + _ => panic!("Expected LineAnchor"), + } + + fs::remove_dir_all(workspace_root).unwrap(); +} diff --git a/crates/frilvault-core/src/tests/yaml_parser_test.rs b/crates/frilvault-core/src/tests/yaml_parser_test.rs new file mode 100644 index 0000000..6939ae0 --- /dev/null +++ b/crates/frilvault-core/src/tests/yaml_parser_test.rs @@ -0,0 +1,54 @@ +use crate::{ + note::{LineAnchor, Note, NoteAnchor, NoteFile}, + parser::{NoteParser, YamlParser}, +}; + +use chrono::Utc; +use uuid::Uuid; + +#[test] +fn serialize_note_file() { + let parser = YamlParser; + + let note = Note { + id: Uuid::new_v4(), + source_file: "src/main.rs".into(), + anchor: NoteAnchor::Line(LineAnchor { + line: 10, + column: 5, + }), + content: "hello".to_string(), + created_at: Utc::now(), + updated_at: Utc::now(), + }; + + let note_file = NoteFile { notes: vec![note] }; + + let yaml = parser.serialize(¬e_file).unwrap(); + + assert!(yaml.contains("hello")); +} + +#[test] +fn deserialize_note_file() { + let parser = YamlParser; + + let yaml = r#" +notes: + - id: "550e8400-e29b-41d4-a716-446655440000" + source_file: src/main.rs + anchor: + type: Line + line: 10 + column: 5 + content: hello + created_at: 2025-01-01T00:00:00Z + updated_at: 2025-01-01T00:00:00Z +"#; + + let note_file = parser.deserialize(yaml).unwrap(); + + assert_eq!(note_file.notes.len(), 1); + + assert_eq!(note_file.notes[0].content, "hello"); +} diff --git a/crates/frilvault-core/src/workspace/mod.rs b/crates/frilvault-core/src/workspace/mod.rs new file mode 100644 index 0000000..4462a30 --- /dev/null +++ b/crates/frilvault-core/src/workspace/mod.rs @@ -0,0 +1,5 @@ +mod models; +mod path_resolver; + +pub use models::*; +pub use path_resolver::*; diff --git a/crates/frilvault-core/src/workspace/models.rs b/crates/frilvault-core/src/workspace/models.rs new file mode 100644 index 0000000..4ad376c --- /dev/null +++ b/crates/frilvault-core/src/workspace/models.rs @@ -0,0 +1,12 @@ +use std::path::PathBuf; + +#[derive(Debug, Clone)] +pub struct Workspace { + pub root: PathBuf, +} + +impl Workspace { + pub fn new(root: impl Into) -> Self { + Self { root: root.into() } + } +} diff --git a/crates/frilvault-core/src/workspace/path_resolver.rs b/crates/frilvault-core/src/workspace/path_resolver.rs new file mode 100644 index 0000000..2f85c71 --- /dev/null +++ b/crates/frilvault-core/src/workspace/path_resolver.rs @@ -0,0 +1,42 @@ +use crate::{ + FrilVaultError, FrilVaultResult, + constants::{NOTE_FILE_EXTENSION, VAULT_DIR_NAME}, +}; +use std::path::{Path, PathBuf}; + +#[derive(Debug, Clone)] +pub struct PathResolver { + workspace_root: PathBuf, +} + +impl PathResolver { + pub fn new(workspace_root: impl Into) -> Self { + Self { + workspace_root: workspace_root.into(), + } + } + + pub fn note_file_name(source_file: impl AsRef) -> String { + format!("{}.{}", source_file.as_ref().display(), NOTE_FILE_EXTENSION) + } + + // Convert the relative path of the source file to the path '.vault/{source_file}.yml' + pub fn resolve_note_path(&self, source_file: impl AsRef) -> PathBuf { + let note_file_name = Self::note_file_name(source_file); + + self.workspace_root + .join(VAULT_DIR_NAME) + .join(note_file_name) + } + + // Converting an Absolute Path to a Relative Path + pub fn to_workspace_relative(&self, source_file: impl AsRef) -> FrilVaultResult { + let source_file = source_file.as_ref(); + + let relative = source_file + .strip_prefix(&self.workspace_root) + .map_err(|_| FrilVaultError::SourcePathOutsideWorkspace)?; + + Ok(relative.to_path_buf()) + } +}