From 57f7b218fb381bcdee45a9f8bf942d5b9358113f Mon Sep 17 00:00:00 2001 From: Miroito Date: Fri, 3 Feb 2023 11:46:30 +0100 Subject: [PATCH] Combined repo initial commit --- .gitignore | 6 + Cargo.lock | 4725 +++++++++++++++++ Cargo.toml | 22 + client/.gitignore | 2 + client/Cargo.toml | 16 + client/index.html | 9 + client/src/api/mod.rs | 2 + client/src/api/routes/mod.rs | 1 + client/src/api/routes/transaction.rs | 19 + client/src/api/types/company.rs | 8 + client/src/api/types/mod.rs | 3 + client/src/api/types/paginated_response.rs | 84 + client/src/api/types/transaction.rs | 36 + client/src/components/base_table.rs | 94 + client/src/components/loading.rs | 19 + client/src/components/mod.rs | 4 + client/src/components/paginated_data_table.rs | 126 + client/src/components/the_header.rs | 18 + client/src/error_pages.rs | 17 + client/src/global_state.rs | 15 + client/src/lib.rs | 15 + client/src/templates/index.rs | 95 + client/src/templates/mod.rs | 1 + client/static/style.css | 3 + client/static/tailwind.css | 798 +++ client/tailwind.config.js | 4 + makefile | 17 + server/Cargo.toml | 35 + server/migration/.gitignore | 1 + server/migration/Cargo.lock | 2188 ++++++++ server/migration/Cargo.toml | 19 + server/migration/README.md | 41 + server/migration/src/lib.rs | 18 + .../m20230112_115856_create_company_table.rs | 52 + ...0230112_160440_create_transaction_table.rs | 78 + ...39_create_transactions_in_process_table.rs | 66 + server/migration/src/main.rs | 6 + server/src/amf/mod.rs | 11 + server/src/amf/service/amf_response.rs | 66 + server/src/amf/service/information_req.rs | 60 + server/src/amf/service/mod.rs | 6 + server/src/amf/service/pdf.rs | 237 + server/src/amf/service/test/amf_response.rs | 18 + server/src/amf/service/test/mod.rs | 2 + server/src/amf/service/test/pdf.rs | 35 + server/src/amf/types/amf_response.rs | 187 + server/src/amf/types/date.rs | 93 + server/src/amf/types/mod.rs | 8 + server/src/amf/types/test/mod.rs | 26 + server/src/amf/types/transaction_data.rs | 16 + server/src/cors.rs | 25 + server/src/db/mod.rs | 47 + server/src/db/paginate.rs | 102 + server/src/db/slug.rs | 31 + server/src/env.rs | 85 + server/src/lib.rs | 86 + server/src/logger/mod.rs | 7 + server/src/model/company.rs | 29 + server/src/model/in_process_transaction.rs | 24 + server/src/model/mod.rs | 7 + server/src/model/prelude.rs | 5 + server/src/model/transaction.rs | 44 + server/src/repo/company.rs | 49 + server/src/repo/in_process_transaction.rs | 148 + server/src/repo/mod.rs | 3 + server/src/repo/transaction.rs | 138 + server/src/route/company.rs | 56 + server/src/route/in_process_transaction.rs | 125 + server/src/route/mod.rs | 3 + server/src/route/transaction.rs | 140 + server/src/task/get_amf_transactions.rs | 138 + server/src/task/mod.rs | 41 + src/bin/server.rs | 6 + src/lib.rs | 2 + 74 files changed, 10769 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 client/.gitignore create mode 100644 client/Cargo.toml create mode 100644 client/index.html create mode 100644 client/src/api/mod.rs create mode 100644 client/src/api/routes/mod.rs create mode 100644 client/src/api/routes/transaction.rs create mode 100644 client/src/api/types/company.rs create mode 100644 client/src/api/types/mod.rs create mode 100644 client/src/api/types/paginated_response.rs create mode 100644 client/src/api/types/transaction.rs create mode 100644 client/src/components/base_table.rs create mode 100644 client/src/components/loading.rs create mode 100644 client/src/components/mod.rs create mode 100644 client/src/components/paginated_data_table.rs create mode 100644 client/src/components/the_header.rs create mode 100644 client/src/error_pages.rs create mode 100644 client/src/global_state.rs create mode 100644 client/src/lib.rs create mode 100644 client/src/templates/index.rs create mode 100644 client/src/templates/mod.rs create mode 100644 client/static/style.css create mode 100644 client/static/tailwind.css create mode 100644 client/tailwind.config.js create mode 100644 makefile create mode 100644 server/Cargo.toml create mode 100644 server/migration/.gitignore create mode 100644 server/migration/Cargo.lock create mode 100644 server/migration/Cargo.toml create mode 100644 server/migration/README.md create mode 100644 server/migration/src/lib.rs create mode 100644 server/migration/src/m20230112_115856_create_company_table.rs create mode 100644 server/migration/src/m20230112_160440_create_transaction_table.rs create mode 100644 server/migration/src/m20230119_112539_create_transactions_in_process_table.rs create mode 100644 server/migration/src/main.rs create mode 100644 server/src/amf/mod.rs create mode 100644 server/src/amf/service/amf_response.rs create mode 100644 server/src/amf/service/information_req.rs create mode 100644 server/src/amf/service/mod.rs create mode 100644 server/src/amf/service/pdf.rs create mode 100644 server/src/amf/service/test/amf_response.rs create mode 100644 server/src/amf/service/test/mod.rs create mode 100644 server/src/amf/service/test/pdf.rs create mode 100644 server/src/amf/types/amf_response.rs create mode 100644 server/src/amf/types/date.rs create mode 100644 server/src/amf/types/mod.rs create mode 100644 server/src/amf/types/test/mod.rs create mode 100644 server/src/amf/types/transaction_data.rs create mode 100644 server/src/cors.rs create mode 100644 server/src/db/mod.rs create mode 100644 server/src/db/paginate.rs create mode 100644 server/src/db/slug.rs create mode 100644 server/src/env.rs create mode 100644 server/src/lib.rs create mode 100644 server/src/logger/mod.rs create mode 100644 server/src/model/company.rs create mode 100644 server/src/model/in_process_transaction.rs create mode 100644 server/src/model/mod.rs create mode 100644 server/src/model/prelude.rs create mode 100644 server/src/model/transaction.rs create mode 100644 server/src/repo/company.rs create mode 100644 server/src/repo/in_process_transaction.rs create mode 100644 server/src/repo/mod.rs create mode 100644 server/src/repo/transaction.rs create mode 100644 server/src/route/company.rs create mode 100644 server/src/route/in_process_transaction.rs create mode 100644 server/src/route/mod.rs create mode 100644 server/src/route/transaction.rs create mode 100644 server/src/task/get_amf_transactions.rs create mode 100644 server/src/task/mod.rs create mode 100644 src/bin/server.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17d1306 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/target +.env + +./client/.perseus +./client/pkg + diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..5ce1f84 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4725 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" +dependencies = [ + "cfg-if 1.0.0", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check 0.9.4", +] + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + +[[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 = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "async-channel" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", + "tokio", +] + +[[package]] +name = "async-io" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" +dependencies = [ + "async-lock", + "autocfg", + "concurrent-queue", + "futures-lite", + "libc", + "log 0.4.17", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "windows-sys 0.42.0", +] + +[[package]] +name = "async-lock" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +dependencies = [ + "event-listener", + "futures-lite", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-attributes", + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log 0.4.17", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "async-task" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + +[[package]] +name = "async-trait" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "atoi" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "atomic-waker" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bae" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" +dependencies = [ + "heck 0.3.3", + "proc-macro-error", + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +dependencies = [ + "byteorder", + "safemem", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" + +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + +[[package]] +name = "base64ct" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" + +[[package]] +name = "binascii" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", +] + +[[package]] +name = "borsh" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +dependencies = [ + "borsh-derive", + "hashbrown 0.11.2", +] + +[[package]] +name = "borsh-derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate", + "proc-macro2 1.0.50", + "syn 1.0.107", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] +name = "bytecheck" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d11cac2c12b5adc6570dad2ee1b87eff4955dac476fe12d81e5fdd352e52406f" +dependencies = [ + "bytecheck_derive", + "ptr_meta", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "serde", + "time 0.1.45", + "wasm-bindgen", + "winapi 0.3.9", +] + +[[package]] +name = "cipher" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clap" +version = "3.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +dependencies = [ + "heck 0.4.1", + "proc-macro-error", + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "client" +version = "0.1.0" +dependencies = [ + "chrono", + "dotenvy", + "envy", + "perseus", + "reqwasm", + "serde", + "serde_json", + "sycamore", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "concurrent-queue" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen", +] + +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + +[[package]] +name = "const_fn" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" + +[[package]] +name = "cookie" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be2018768ed1d848cc4d347d551546474025ba820e5db70e4c9aaa349f678bd7" +dependencies = [ + "percent-encoding 2.2.0", + "time 0.1.45", +] + +[[package]] +name = "cookie" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" +dependencies = [ + "aes-gcm", + "base64 0.20.0", + "hkdf", + "hmac", + "percent-encoding 2.2.0", + "rand", + "sha2", + "subtle", + "time 0.3.17", + "version_check 0.9.4", +] + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "cxx" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc831ee6a32dd495436e317595e639a587aa9907bef96fe6e6abc290ab6204e9" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94331d54f1b1a8895cd81049f7eaaaef9d05a7dcb4d1fd08bf3ff0806246789d" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2 1.0.50", + "quote 1.0.23", + "scratch", + "syn 1.0.107", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48dcd35ba14ca9b40d6e4b4b39961f23d835dbb8eed74565ded361d93e1feb8a" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bbeb29798b407ccd82a3324ade1a7286e0d29851475990b612670f6f5124d2" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2 1.0.50", + "quote 1.0.23", + "strsim", + "syn 1.0.107", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", + "crypto-bigint", + "pem-rfc7468", +] + +[[package]] +name = "deunicode" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" + +[[package]] +name = "devise" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd716c4a507adc5a2aa7c2a372d06c7497727e0892b243d3036bc7478a13e526" +dependencies = [ + "devise_codegen 0.2.1", + "devise_core 0.2.1", +] + +[[package]] +name = "devise" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c7580b072f1c8476148f16e0a0d5dedddab787da98d86c5082c5e9ed8ab595" +dependencies = [ + "devise_codegen 0.3.1", + "devise_core 0.3.1", +] + +[[package]] +name = "devise_codegen" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea7b8290d118127c08e3669da20b331bed56b09f20be5945b7da6c116d8fab53" +dependencies = [ + "devise_core 0.2.1", + "quote 0.6.13", +] + +[[package]] +name = "devise_codegen" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123c73e7a6e51b05c75fe1a1b2f4e241399ea5740ed810b0e3e6cacd9db5e7b2" +dependencies = [ + "devise_core 0.3.1", + "quote 1.0.23", +] + +[[package]] +name = "devise_core" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1053e9d5d5aade9bcedb5ab53b78df2b56ff9408a3138ce77eaaef87f932373" +dependencies = [ + "bitflags", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "devise_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841ef46f4787d9097405cac4e70fb8644fc037b526e8c14054247c0263c400d0" +dependencies = [ + "bitflags", + "proc-macro2 1.0.50", + "proc-macro2-diagnostics", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" + +[[package]] +name = "dotenvy" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d8c417d7a8cb362e0c37e5d815f5eb7c37f79ff93707329d5a194e42e54ca0" + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "encoding" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +dependencies = [ + "encoding-index-japanese", + "encoding-index-korean", + "encoding-index-simpchinese", + "encoding-index-singlebyte", + "encoding-index-tradchinese", +] + +[[package]] +name = "encoding-index-japanese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-korean" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-simpchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-singlebyte" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-tradchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding_index_tests" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log 0.4.17", + "regex", + "termcolor", +] + +[[package]] +name = "envy" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" +dependencies = [ + "serde", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fast-insiders" +version = "0.1.0" +dependencies = [ + "client", + "server", +] + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "figment" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e56602b469b2201400dec66a66aec5a9b8761ee97cd1b8c96ab2483fcc16cc9" +dependencies = [ + "atomic", + "pear 0.2.3", + "serde", + "toml 0.5.11", + "uncased", + "version_check 0.9.4", +] + +[[package]] +name = "filetime" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "windows-sys 0.42.0", +] + +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fmterr" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a224f8df6326425eee955a654c558a6459ae6f2c9a5a715b42856790df24222" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding 2.2.0", +] + +[[package]] +name = "fsevent" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" +dependencies = [ + "bitflags", + "fsevent-sys", +] + +[[package]] +name = "fsevent-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" +dependencies = [ + "libc", +] + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + +[[package]] +name = "futures" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" + +[[package]] +name = "futures-executor" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot 0.11.2", +] + +[[package]] +name = "futures-io" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "futures-sink" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" + +[[package]] +name = "futures-task" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" + +[[package]] +name = "futures-util" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generator" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266041a359dfa931b370ef684cceb84b166beb14f7f0421f4a6a3d0c446d12e" +dependencies = [ + "cc", + "libc", + "log 0.4.17", + "rustversion", + "windows", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check 0.9.4", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "ghash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "gloo-net" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2899cb1a13be9020b010967adc6b2a8a343b6f1428b90238c9d53ca24decc6db" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "gloo-utils" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e8fc851e9c7b9852508bc6e3f690f452f474417e8545ec9857b7f7377036b5" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "h2" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" +dependencies = [ + "hashbrown 0.12.3", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "html-escape" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" +dependencies = [ + "utf8-width", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "hyper" +version = "0.10.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" +dependencies = [ + "base64 0.9.3", + "httparse", + "language-tags", + "log 0.3.9", + "mime 0.2.6", + "num_cpus", + "time 0.1.45", + "traitobject", + "typeable", + "unicase", + "url 1.7.2", +] + +[[package]] +name = "hyper" +version = "0.14.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper 0.14.24", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi 0.3.9", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "inlinable_string" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" + +[[package]] +name = "inotify" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "ipnet" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log 0.4.17", +] + +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "lexical" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7aefb36fd43fef7003334742cbf77b243fcd36418a1d1bdd480d613a67968f6" +dependencies = [ + "lexical-core", +] + +[[package]] +name = "lexical-core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" +dependencies = [ + "lexical-parse-float", + "lexical-parse-integer", + "lexical-util", + "lexical-write-float", + "lexical-write-integer", +] + +[[package]] +name = "lexical-parse-float" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" +dependencies = [ + "lexical-parse-integer", + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-parse-integer" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" +dependencies = [ + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-util" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "lexical-write-float" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" +dependencies = [ + "lexical-util", + "lexical-write-integer", + "static_assertions", +] + +[[package]] +name = "lexical-write-integer" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" +dependencies = [ + "lexical-util", + "static_assertions", +] + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.17", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if 1.0.0", + "value-bag", +] + +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if 1.0.0", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "lopdf" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0f69c40d6dbc68ebac4bf5aec3d9978e094e22e29fcabd045acd9cec74a9dc" +dependencies = [ + "chrono", + "encoding", + "flate2", + "itoa", + "linked-hash-map", + "log 0.4.17", + "pom", + "time 0.2.27", + "weezl", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "migration" +version = "0.1.0" +dependencies = [ + "async-std", + "sea-orm-migration", +] + +[[package]] +name = "mime" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +dependencies = [ + "log 0.3.9", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log 0.4.17", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "mio" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +dependencies = [ + "libc", + "log 0.4.17", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.42.0", +] + +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log 0.4.17", + "mio 0.6.23", + "slab", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "multer" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed4198ce7a4cbd2a57af78d28c6fbb57d81ac5f1d6ad79ac6c5587419cbdf22" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "log 0.4.17", + "memchr", + "mime 0.3.16", + "spin 0.9.4", + "tokio", + "tokio-util", + "version_check 0.9.4", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log 0.4.17", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "net2" +version = "0.2.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "notify" +version = "4.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257" +dependencies = [ + "bitflags", + "filetime", + "fsevent", + "fsevent-sys", + "inotify", + "libc", + "mio 0.6.23", + "mio-extras", + "walkdir", + "winapi 0.3.9", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi 0.3.9", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl" +version = "0.10.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "ouroboros" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbb50b356159620db6ac971c6d5c9ab788c9cc38a6f49619fca2a27acb062ca" +dependencies = [ + "aliasable", + "ouroboros_macro", +] + +[[package]] +name = "ouroboros_macro" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0d9d1a6191c4f391f87219d1ea42b23f09ee84d64763cd05ee6ea88d9f384d" +dependencies = [ + "Inflector", + "proc-macro-error", + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.7", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi 0.3.9", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "smallvec", + "windows-sys 0.45.0", +] + +[[package]] +name = "paste" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" + +[[package]] +name = "pear" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32dfa7458144c6af7f9ce6a137ef975466aa68ffa44d4d816ee5934018ba960a" +dependencies = [ + "pear_codegen 0.1.5", +] + +[[package]] +name = "pear" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e44241c5e4c868e3eaa78b7c1848cadd6344ed4f54d029832d32b415a58702" +dependencies = [ + "inlinable_string", + "pear_codegen 0.2.3", + "yansi", +] + +[[package]] +name = "pear_codegen" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0288ba5d581afbc93e2bbd931c1013584c15ecf46b1cdb927edc7abddbc8ca6" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", + "version_check 0.9.4", + "yansi", +] + +[[package]] +name = "pear_codegen" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a5ca643c2303ecb740d506539deba189e16f2754040a42901cd8105d0282d0" +dependencies = [ + "proc-macro2 1.0.50", + "proc-macro2-diagnostics", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "pem-rfc7468" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01de5d978f34aa4b2296576379fcc416034702fd94117c56ffd8a1a767cefb30" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "perseus" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0f6fff08e4cf346b91bd7c09b523e6bc6c0a45b6751bd1951ec8462bf774c95" +dependencies = [ + "async-trait", + "chrono", + "fmterr", + "futures", + "http", + "js-sys", + "perseus-macro", + "regex", + "rexie", + "serde", + "serde_json", + "sycamore", + "sycamore-router", + "thiserror", + "tokio", + "urlencoding", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "perseus-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23876d449f9ce8f4f82207406863d9f75afda68dbf7951d14452e0d6e0b1e745" +dependencies = [ + "darling", + "proc-macro2 1.0.50", + "quote 1.0.23", + "serde_json", + "sycamore-reactive", + "syn 1.0.107", +] + +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a78f66c04ccc83dd4486fd46c33896f4e17b24a7a3a6400dedc48ed0ddd72320" +dependencies = [ + "der", + "pkcs8", + "zeroize", +] + +[[package]] +name = "pkcs8" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +dependencies = [ + "der", + "spki", + "zeroize", +] + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "polling" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", + "libc", + "log 0.4.17", + "wepoll-ffi", + "windows-sys 0.42.0", +] + +[[package]] +name = "polyval" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "pom" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e2192780e9f8e282049ff9bffcaa28171e1cb0844f49ed5374e518ae6024ec" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "pretty_env_logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" +dependencies = [ + "env_logger", + "log 0.4.17", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml 0.5.11", +] + +[[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 1.0.50", + "quote 1.0.23", + "syn 1.0.107", + "version_check 0.9.4", +] + +[[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 1.0.50", + "quote 1.0.23", + "version_check 0.9.4", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", + "version_check 0.9.4", + "yansi", +] + +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2 1.0.50", +] + +[[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 = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c78fb8c9293bcd48ef6fce7b4ca950ceaf21210de6e105a883ee280c0f7b9ed" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f9c0c92af03644e4806106281fe2e068ac5bc0ae74a707266d06ea27bccee5f" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "rend" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "reqwasm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b89870d729c501fa7a68c43bf4d938bbb3a8c156d333d90faa0e8b3e3212fb" +dependencies = [ + "gloo-net", +] + +[[package]] +name = "reqwest" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" +dependencies = [ + "base64 0.21.0", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper 0.14.24", + "hyper-tls", + "ipnet", + "js-sys", + "log 0.4.17", + "mime 0.3.16", + "native-tls", + "once_cell", + "percent-encoding 2.2.0", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url 2.3.1", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "rexie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ed2b22c65c32a8bd7cc1517fe02a8240839cba64e4cba7787e758f70f011b25" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "num-traits", + "thiserror", + "tokio", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi 0.3.9", +] + +[[package]] +name = "rkyv" +version = "0.7.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" +dependencies = [ + "bytecheck", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "rocket" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83b9d9dc08c5dcc1d8126a9dd615545e6a358f8c13c883c8dfed8c0376fa355e" +dependencies = [ + "atty", + "base64 0.13.1", + "log 0.4.17", + "memchr", + "num_cpus", + "pear 0.1.5", + "rocket_codegen 0.4.11", + "rocket_http 0.4.11", + "state 0.4.2", + "time 0.1.45", + "toml 0.4.10", + "version_check 0.9.4", + "yansi", +] + +[[package]] +name = "rocket" +version = "0.5.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ead083fce4a405feb349cf09abdf64471c6077f14e0ce59364aa90d4b99317" +dependencies = [ + "async-stream", + "async-trait", + "atomic", + "atty", + "binascii", + "bytes", + "either", + "figment", + "futures", + "indexmap", + "log 0.4.17", + "memchr", + "multer", + "num_cpus", + "parking_lot 0.12.1", + "pin-project-lite", + "rand", + "ref-cast", + "rocket_codegen 0.5.0-rc.2", + "rocket_http 0.5.0-rc.2", + "serde", + "serde_json", + "state 0.5.3", + "tempfile", + "time 0.3.17", + "tokio", + "tokio-stream", + "tokio-util", + "ubyte", + "version_check 0.9.4", + "yansi", +] + +[[package]] +name = "rocket_codegen" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2810037b5820098af97bd4fdd309e76a8101ceb178147de775c835a2537284fe" +dependencies = [ + "devise 0.2.1", + "glob", + "indexmap", + "quote 0.6.13", + "rocket_http 0.4.11", + "version_check 0.9.4", + "yansi", +] + +[[package]] +name = "rocket_codegen" +version = "0.5.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6aeb6bb9c61e9cd2c00d70ea267bf36f76a4cc615e5908b349c2f9d93999b47" +dependencies = [ + "devise 0.3.1", + "glob", + "indexmap", + "proc-macro2 1.0.50", + "quote 1.0.23", + "rocket_http 0.5.0-rc.2", + "syn 1.0.107", + "unicode-xid 0.2.4", +] + +[[package]] +name = "rocket_contrib" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e20efbc6a211cb3df5375accf532d4186f224b623f39eca650b19b96240c596b" +dependencies = [ + "log 0.4.17", + "notify", + "rocket 0.4.11", + "serde", + "serde_json", +] + +[[package]] +name = "rocket_http" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf9cbd128e1f321a2d0bebd2b7cf0aafd89ca43edf69e49b56a5c46e48eb19f" +dependencies = [ + "cookie 0.11.5", + "hyper 0.10.16", + "indexmap", + "pear 0.1.5", + "percent-encoding 1.0.1", + "smallvec", + "state 0.4.2", + "time 0.1.45", + "unicode-xid 0.1.0", +] + +[[package]] +name = "rocket_http" +version = "0.5.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ded65d127954de3c12471630bf4b81a2792f065984461e65b91d0fdaafc17a2" +dependencies = [ + "cookie 0.16.2", + "either", + "futures", + "http", + "hyper 0.14.24", + "indexmap", + "log 0.4.17", + "memchr", + "pear 0.2.3", + "percent-encoding 2.2.0", + "pin-project-lite", + "ref-cast", + "serde", + "smallvec", + "stable-pattern", + "state 0.5.3", + "time 0.3.17", + "tokio", + "uncased", +] + +[[package]] +name = "rsa" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" +dependencies = [ + "byteorder", + "digest", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "smallvec", + "subtle", + "zeroize", +] + +[[package]] +name = "rust_decimal" +version = "1.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe32e8c89834541077a5c5bbe5691aa69324361e27e6aeb3552a737db4a70c8" +dependencies = [ + "arrayvec", + "borsh", + "bytecheck", + "byteorder", + "bytes", + "num-traits", + "rand", + "rkyv", + "serde", + "serde_json", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +dependencies = [ + "log 0.4.17", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64 0.21.0", +] + +[[package]] +name = "rustversion" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys 0.42.0", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sea-orm" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88694d01b528a94f90ad87f8d2f546d060d070eee180315c67d158cb69476034" +dependencies = [ + "async-stream", + "async-trait", + "chrono", + "futures", + "futures-util", + "log 0.4.17", + "ouroboros", + "rust_decimal", + "sea-orm-macros", + "sea-query", + "sea-query-binder", + "sea-strum", + "serde", + "serde_json", + "sqlx", + "thiserror", + "time 0.3.17", + "tracing", + "url 2.3.1", + "uuid", +] + +[[package]] +name = "sea-orm-cli" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ebe1f820fe8949cf6a57272ba9ebd0be766e47c9b85c04b3cabea40ab9459b3" +dependencies = [ + "chrono", + "clap", + "dotenvy", + "regex", + "sea-schema", + "tracing", + "tracing-subscriber", + "url 2.3.1", +] + +[[package]] +name = "sea-orm-macros" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7216195de9c6b2474fd0efab486173dccd0eff21f28cc54aa4c0205d52fb3af0" +dependencies = [ + "bae", + "heck 0.3.3", + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "sea-orm-migration" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed3cdfa669e4c385922f902b9a58e0c2128782a4d0fe79c6c34f3b927565e5b" +dependencies = [ + "async-trait", + "clap", + "dotenvy", + "sea-orm", + "sea-orm-cli", + "sea-schema", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "sea-orm-rocket" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30f30b2cf45d317def42af8542635e341fa4ae12fb0697a713346750ff426aa2" +dependencies = [ + "rocket 0.5.0-rc.2", + "sea-orm-rocket-codegen", +] + +[[package]] +name = "sea-orm-rocket-codegen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfd750adb2541f30b855e2d86e90bf7031ac17e048ac5226a8e8c8d8a6022f2" +dependencies = [ + "devise 0.3.1", + "quote 1.0.23", +] + +[[package]] +name = "sea-query" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f0fc4d8e44e1d51c739a68d336252a18bc59553778075d5e32649be6ec92ed" +dependencies = [ + "chrono", + "rust_decimal", + "sea-query-derive", + "serde_json", + "time 0.3.17", + "uuid", +] + +[[package]] +name = "sea-query-binder" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2585b89c985cfacfe0ec9fc9e7bb055b776c1a2581c4e3c6185af2b8bf8865" +dependencies = [ + "chrono", + "rust_decimal", + "sea-query", + "serde_json", + "sqlx", + "time 0.3.17", + "uuid", +] + +[[package]] +name = "sea-query-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cdc022b4f606353fe5dc85b09713a04e433323b70163e81513b141c6ae6eb5" +dependencies = [ + "heck 0.3.3", + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", + "thiserror", +] + +[[package]] +name = "sea-schema" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d5fda574d980e9352b6c7abd6fc75697436fe0078cac2b548559b52643ad3b" +dependencies = [ + "futures", + "sea-query", + "sea-schema-derive", +] + +[[package]] +name = "sea-schema-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56821b7076f5096b8f726e2791ad255a99c82498e08ec477a65a96c461ff1927" +dependencies = [ + "heck 0.3.3", + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "sea-strum" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391d06a6007842cfe79ac6f7f53911b76dfd69fc9a6769f1cf6569d12ce20e1b" +dependencies = [ + "sea-strum_macros", +] + +[[package]] +name = "sea-strum_macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b4397b825df6ccf1e98bcdabef3bbcfc47ff5853983467850eeab878384f21" +dependencies = [ + "heck 0.3.3", + "proc-macro2 1.0.50", + "quote 1.0.23", + "rustversion", + "syn 1.0.107", +] + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "security-framework" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "serde_json" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "server" +version = "0.1.0" +dependencies = [ + "async-trait", + "bytes", + "chrono", + "dotenvy", + "envy", + "futures", + "lazy_static", + "log 0.4.17", + "lopdf", + "migration", + "perseus", + "pretty_env_logger", + "reqwest", + "rocket 0.5.0-rc.2", + "rocket_contrib", + "sea-orm", + "sea-orm-rocket", + "sea-query", + "serde", + "serde_json", + "slug", + "thiserror", + "tokio", +] + +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slug" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" +dependencies = [ + "deunicode", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" + +[[package]] +name = "spki" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlformat" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c12bc9199d1db8234678b7051747c07f517cdcf019262d1847b94ec8b1aee3e" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9249290c05928352f71c077cc44a464d880c63f26f7534728cca008e135c0428" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" +dependencies = [ + "ahash", + "atoi", + "bitflags", + "byteorder", + "bytes", + "chrono", + "crc", + "crossbeam-queue", + "digest", + "dotenvy", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-util", + "generic-array", + "hashlink", + "hex", + "indexmap", + "itoa", + "libc", + "log 0.4.17", + "memchr", + "num-bigint", + "once_cell", + "paste", + "percent-encoding 2.2.0", + "rand", + "rsa", + "rust_decimal", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "sha1 0.10.5", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "time 0.3.17", + "tokio-stream", + "url 2.3.1", + "uuid", + "webpki-roots", +] + +[[package]] +name = "sqlx-macros" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b850fa514dc11f2ee85be9d055c512aa866746adfacd1cb42d867d68e6a5b0d9" +dependencies = [ + "dotenvy", + "either", + "heck 0.4.1", + "once_cell", + "proc-macro2 1.0.50", + "quote 1.0.23", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn 1.0.107", + "url 2.3.1", +] + +[[package]] +name = "sqlx-rt" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "stable-pattern" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045" +dependencies = [ + "memchr", +] + +[[package]] +name = "standback" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" +dependencies = [ + "version_check 0.9.4", +] + +[[package]] +name = "state" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483" + +[[package]] +name = "state" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" +dependencies = [ + "loom", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stdweb" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" +dependencies = [ + "discard", + "rustc_version", + "stdweb-derive", + "stdweb-internal-macros", + "stdweb-internal-runtime", + "wasm-bindgen", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "serde", + "serde_derive", + "syn 1.0.107", +] + +[[package]] +name = "stdweb-internal-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" +dependencies = [ + "base-x", + "proc-macro2 1.0.50", + "quote 1.0.23", + "serde", + "serde_derive", + "serde_json", + "sha1 0.6.1", + "syn 1.0.107", +] + +[[package]] +name = "stdweb-internal-runtime" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" + +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "sycamore" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5cea65876897bb946a623e16bf3df2de4997a6872d95b99dfaed5dd8e14e264" +dependencies = [ + "ahash", + "html-escape", + "indexmap", + "js-sys", + "lexical", + "once_cell", + "paste", + "smallvec", + "sycamore-macro", + "sycamore-reactive", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "sycamore-macro" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6911dba86d928ed3c898ee182c1a8a9f00299aa78875bc9308e7fd389e5bb4" +dependencies = [ + "once_cell", + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "sycamore-reactive" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20809429d0f9c2ffcbb3f192957a5d0c505519138e41c5d38808c5b42b3c53ab" +dependencies = [ + "ahash", + "indexmap", + "serde", + "smallvec", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "sycamore-router" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cace57b69d923ef7ac5a1291bee73fa62e7d75b1f3a713db70d30ab0ee032185" +dependencies = [ + "sycamore", + "sycamore-router-macro", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "sycamore-router-macro" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a1f83a4862484dba897a6dc64c4a72b5c808c9af05573f7a55133b4f110ac66" +dependencies = [ + "nom", + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", + "unicode-xid 0.2.4", +] + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if 1.0.0", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi 0.3.9", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", +] + +[[package]] +name = "time" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" +dependencies = [ + "const_fn", + "libc", + "standback", + "stdweb", + "time-macros 0.1.1", + "version_check 0.9.4", + "winapi 0.3.9", +] + +[[package]] +name = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros 0.2.6", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" +dependencies = [ + "proc-macro-hack", + "time-macros-impl", +] + +[[package]] +name = "time-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + +[[package]] +name = "time-macros-impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" +dependencies = [ + "proc-macro-hack", + "proc-macro2 1.0.50", + "quote 1.0.23", + "standback", + "syn 1.0.107", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio 0.8.5", + "num_cpus", + "once_cell", + "parking_lot 0.12.1", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "winapi 0.3.9", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-stream" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +dependencies = [ + "serde", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if 1.0.0", + "log 0.4.17", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log 0.4.17", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "ubyte" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c81f0dae7d286ad0d9366d7679a77934cfc3cf3a8d67e82669794412b2368fe6" +dependencies = [ + "serde", +] + +[[package]] +name = "uncased" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" +dependencies = [ + "serde", + "version_check 0.9.4", +] + +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +dependencies = [ + "version_check 0.1.5", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "universal-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna 0.1.5", + "matches", + "percent-encoding 1.0.1", +] + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna 0.3.0", + "percent-encoding 2.2.0", +] + +[[package]] +name = "urlencoding" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" + +[[package]] +name = "utf8-width" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" + +[[package]] +name = "uuid" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +dependencies = [ + "getrandom", + "serde", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "value-bag" +version = "1.0.0-alpha.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" +dependencies = [ + "ctor", + "version_check 0.9.4", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi 0.3.9", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log 0.4.17", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[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.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if 1.0.0", + "serde", + "serde_json", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log 0.4.17", + "once_cell", + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +dependencies = [ + "cfg-if 1.0.0", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote 1.0.23", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2 1.0.50", + "quote 1.0.23", + "syn 1.0.107", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" +dependencies = [ + "windows_aarch64_msvc 0.39.0", + "windows_i686_gnu 0.39.0", + "windows_i686_msvc 0.39.0", + "windows_x86_64_gnu 0.39.0", + "windows_x86_64_msvc 0.39.0", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e054d51 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "fast-insiders" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +server = { version = "0.1.0", path = "./server" } +client = { version = "0.1.0", path = "./client" } + + +[workspace] +members = ["server", "client"] + +[workspace.dependencies] +chrono = { version = "0.4.23", features = ["serde"] } +serde = { version = "1.0.152", features = ["derive"] } +dotenvy = "0.15.6" +envy = "0.4.2" +serde_json = "1.0.91" +# chrono = { workspace = true, features = ["serde"] } diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 0000000..d421d66 --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,2 @@ +.perseus/ +pkg/ diff --git a/client/Cargo.toml b/client/Cargo.toml new file mode 100644 index 0000000..0cd480e --- /dev/null +++ b/client/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "client" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +chrono = { workspace = true, features = ["serde"] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +dotenvy = { workspace = true } +envy = { workspace = true } +perseus = { version = "0.3.6", features = ["hydrate"] } +sycamore = { version = "0.7.1", features = ["ssr", "serde", "futures"] } +reqwasm = "0.5.0" diff --git a/client/index.html b/client/index.html new file mode 100644 index 0000000..00420c4 --- /dev/null +++ b/client/index.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/src/api/mod.rs b/client/src/api/mod.rs new file mode 100644 index 0000000..a061da8 --- /dev/null +++ b/client/src/api/mod.rs @@ -0,0 +1,2 @@ +pub mod routes; +pub mod types; diff --git a/client/src/api/routes/mod.rs b/client/src/api/routes/mod.rs new file mode 100644 index 0000000..37f0806 --- /dev/null +++ b/client/src/api/routes/mod.rs @@ -0,0 +1 @@ +pub mod transaction; diff --git a/client/src/api/routes/transaction.rs b/client/src/api/routes/transaction.rs new file mode 100644 index 0000000..b43ae20 --- /dev/null +++ b/client/src/api/routes/transaction.rs @@ -0,0 +1,19 @@ +use crate::api::types::{paginated_response::PaginatedResponse, transaction::TransactionCompany}; + +pub async fn get_transactions( + page: i64, + size: i64, +) -> Result, ()> { + let res = reqwasm::http::Request::get(&format!( + "http://localhost:8000/v1/transaction?page={}&size={}", + page, size, + )) + .send() + .await + .unwrap() + .json::>() + .await + .unwrap(); + + Ok(res) +} diff --git a/client/src/api/types/company.rs b/client/src/api/types/company.rs new file mode 100644 index 0000000..19a5eb7 --- /dev/null +++ b/client/src/api/types/company.rs @@ -0,0 +1,8 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Company { + pub id: i32, + pub name: String, + pub slug: String, +} diff --git a/client/src/api/types/mod.rs b/client/src/api/types/mod.rs new file mode 100644 index 0000000..c2d26c4 --- /dev/null +++ b/client/src/api/types/mod.rs @@ -0,0 +1,3 @@ +pub mod company; +pub mod paginated_response; +pub mod transaction; diff --git a/client/src/api/types/paginated_response.rs b/client/src/api/types/paginated_response.rs new file mode 100644 index 0000000..413b4ed --- /dev/null +++ b/client/src/api/types/paginated_response.rs @@ -0,0 +1,84 @@ +use serde::{Deserialize, Serialize}; +use sycamore::{prelude::GenericNode, view}; + +use crate::components::base_table::TableContent; + +use super::transaction::TransactionCompany; + +pub trait IntoTableData +where + G: GenericNode, +{ + fn into_table_data(self) -> TableContent; +} + +#[derive(Clone, Serialize, Deserialize)] +pub struct PaginatedResponse { + pub count: i64, + pub num_pages: i64, + pub list: Vec, +} + +impl IntoTableData for PaginatedResponse +where + G: GenericNode, +{ + fn into_table_data(self) -> TableContent { + let headers_view = vec![ + view! { "Company" }, + view! { "Date published" }, + view! { "Date executed" }, + view! { "Person" }, + view! { "Nature" }, + view! { "ISIN" }, + view! { "Instrument" }, + view! { "Exchange" }, + view! { "Volume" }, + view! { "Unit price" }, + view! { "Total" }, + ]; + + let data_view: Vec>> = self + .list + .into_iter() + .map(|t| { + let mut res = vec![]; + let t1 = t.clone(); + res.push(view! { + a (href=format!("index/{}", t1.company.slug), + class="text-indigo-800 dark:text-indigo-300 hover:text-indigo-500 dark:hover:text-indigo-600 hover:underline", + ) { + (t1.company.name.to_owned()) + } + }); + let t1 = t.clone(); + res.push(view! { (t1.date_published.to_owned()) }); + let t1 = t.clone(); + res.push(view! { (t1.date_executed.to_owned()) }); + let t1 = t.clone(); + res.push(view! { (t1.person.to_owned()) }); + let t1 = t.clone(); + res.push(view! { (t1.nature.to_owned()) }); + let t1 = t.clone(); + res.push(view! { (t1.isin.to_owned().unwrap_or("-".to_string())) }); + let t1 = t.clone(); + res.push(view! { (t1.instrument.to_owned()) }); + let t1 = t.clone(); + res.push(view! { (t1.exchange.to_owned()) }); + let t1 = t.clone(); + res.push(view! { (t1.volume.to_owned()) }); + let t1 = t.clone(); + res.push(view! { (t1.unit_price.to_owned()) }); + let t1 = t.clone(); + res.push(view! { ((t1.volume as f32 * t1.unit_price).to_string()) }); + + res + }) + .collect(); + + TableContent { + headers_view, + data_view, + } + } +} diff --git a/client/src/api/types/transaction.rs b/client/src/api/types/transaction.rs new file mode 100644 index 0000000..a681b45 --- /dev/null +++ b/client/src/api/types/transaction.rs @@ -0,0 +1,36 @@ +use chrono::NaiveDate; +use serde::{Deserialize, Serialize}; + +use super::company::Company; + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Transaction { + pub id: i32, + pub company_id: i32, + pub foreign_id: String, + pub date_published: NaiveDate, + pub date_executed: NaiveDate, + pub person: String, + pub exchange: String, + pub nature: String, + pub isin: Option, + pub instrument: String, + pub volume: i32, + pub unit_price: f32, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct TransactionCompany { + pub id: i32, + pub foreign_id: String, + pub date_published: NaiveDate, + pub date_executed: NaiveDate, + pub person: String, + pub exchange: String, + pub nature: String, + pub isin: Option, + pub instrument: String, + pub volume: i32, + pub unit_price: f32, + pub company: Company, +} diff --git a/client/src/components/base_table.rs b/client/src/components/base_table.rs new file mode 100644 index 0000000..f187ecb --- /dev/null +++ b/client/src/components/base_table.rs @@ -0,0 +1,94 @@ +use sycamore::prelude::*; + +#[derive(Debug, Clone)] +pub struct TableContent +where + G: GenericNode, +{ + pub headers_view: Vec>, + pub data_view: Vec>>, +} + +#[derive(Debug, Clone)] +pub struct TableContentRx +where + G: GenericNode, +{ + pub headers_view: Signal>>, + pub data_view: Signal>>>, +} + +#[derive(Debug, Clone)] +struct PEqView(usize, T); + +impl PartialEq> for PEqView { + fn eq(&self, other: &PEqView) -> bool { + self.0 == other.0 + } +} + +impl Eq for PEqView {} + +#[component(BaseTable)] +pub fn the_header( + TableContentRx { + headers_view, + data_view, + }: TableContentRx, +) -> View +where + G: GenericNode, +{ + let headers = create_memo(cloned!((headers_view) => move || { + (*headers_view.get()).clone().into_iter().enumerate().map(|(idx, v)| PEqView(idx,v)).collect::>>>() + })); + + let data = Signal::new(vec![]); + let data2 = data.clone(); + create_effect(cloned!((data_view, data2, data) => move || { + data.set(vec![]); + let v_table = data_view.get(); + for (idx, row) in v_table.iter().enumerate() { + let views = PEqView(idx, View::new_fragment( + row.iter().map(|cell| { + view!{ th (class="m-2 p-2 border-slate-500 border-x border-dashed") { (cell) } } + } ).collect() + )); + + let mut d = (*data2.get()).clone(); + d.push(views); + data.set(d); + } + })); + + view! { + table (class="table-auto bg-slate-200 text-left dark:bg-slate-800 rounded-lg mx-auto my-2") { + thead { + tr (class="border-b-2 border-slate-500 text-center") { + Keyed(KeyedProps { + iterable: headers, + template: |v| { + view! { + th (class="m-2 p-2") { (v.1) } + } + }, + key: |v| v.0, + }) + } + } + tbody { + Keyed(KeyedProps { + iterable: data.handle(), + key: |x| x.0, + template: |t| { + view! { + tr (class="m-2 p-2 border-slate-500 border") { + (t.1) + } + } + }, + }) + } + } + } +} diff --git a/client/src/components/loading.rs b/client/src/components/loading.rs new file mode 100644 index 0000000..9ef0f58 --- /dev/null +++ b/client/src/components/loading.rs @@ -0,0 +1,19 @@ +use sycamore::prelude::*; + +#[component(Loading)] +pub fn component() -> View { + view! { + svg (version="1.1", id="loader-1", xmlns="http://www.w3.org/2000/svg", xlink="http://www.w3.org/1999/xlink", x="0px", y="0px", + width="40px", height="40px", viewBox="0 0 50 50", space="preserve") { + path (fill="#000", d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z"){ + animateTransform (attributeType="xml", + attributeName="transform", + type="rotate", + from="0 25 25", + to="360 25 25", + dur="0.6s", + repeatCount="indefinite") {} + } + } + } +} diff --git a/client/src/components/mod.rs b/client/src/components/mod.rs new file mode 100644 index 0000000..0713042 --- /dev/null +++ b/client/src/components/mod.rs @@ -0,0 +1,4 @@ +pub mod base_table; +pub mod loading; +pub mod paginated_data_table; +pub mod the_header; diff --git a/client/src/components/paginated_data_table.rs b/client/src/components/paginated_data_table.rs new file mode 100644 index 0000000..5ad4b91 --- /dev/null +++ b/client/src/components/paginated_data_table.rs @@ -0,0 +1,126 @@ +use std::{marker::PhantomData, rc::Rc}; + +use serde::Deserialize; +use sycamore::prelude::*; + +use crate::{ + api::types::paginated_response::{IntoTableData, PaginatedResponse}, + components::{ + base_table::{BaseTable, TableContentRx}, + loading::Loading, + }, +}; + +#[perseus::make_rx(PaginatedTableStateRx)] +pub struct PaginatedTableState +where + M: 'static, +{ + pub req: String, + pub ph_data: PhantomData, +} + +#[component(PaginatedTable)] +pub fn component(PaginatedTableStateRx { req, ph_data }: PaginatedTableStateRx) -> View +where + M: 'static, + PaginatedResponse: IntoTableData + Clone, + for<'de> M: Deserialize<'de>, +{ + let paginated_data: Signal>> = Signal::new(None); + let table_prop: TableContentRx = TableContentRx { + headers_view: Signal::new(vec![]), + data_view: Signal::new(vec![vec![]]), + }; + let table_prop2 = table_prop.clone(); + let page: Signal = Signal::new(0); + let n_page: Signal = Signal::new(1); + let n_rows: Signal = Signal::new(0); + + let page_up = cloned!((page, paginated_data, n_page) => move |_| { + n_page.set((*paginated_data.get()).as_ref().map_or(0, |t| t.num_pages)); + if *page.get() + 1 < *n_page.get() { + page.set((*page.get()).min(*n_page.get() - 1) + 1) + } + }); + let page_down = cloned!((page) => move |_| { + if *page.get() > 0 { + page.set((*page.get()-1).max(0)); + } + }); + + let page_size_string = Signal::new("20".to_string()); + let page_size_string2 = page_size_string.clone(); + create_effect( + cloned!((page_size_string, paginated_data, page, req, n_page, n_rows) => move || { + let page = *page.get(); + let page_size_s = page_size_string.get(); + let page_size = page_size_s.parse().unwrap_or(20); + let url = (*req.get()).clone(); + if G::IS_BROWSER { + perseus::spawn_local( + cloned!((table_prop2, page, paginated_data, n_page, n_rows) => async move { + let res = reqwasm::http::Request::get(&format!( + "{}?page={}&size={}", + url, + page, page_size, + )) + .send() + .await + .unwrap() + .json::>() + .await + .unwrap(); + paginated_data.set(Some(res.clone())); + n_rows.set(res.count); + let table_content = res.into_table_data(); + table_prop2.data_view.set(table_content.data_view); + table_prop2.headers_view.set(table_content.headers_view); + n_page.set((*paginated_data.get()).as_ref().map_or(0, |t| t.num_pages)); + }), + ); + } + }), + ); + + view! { + (cloned!((n_rows, page_size_string, page_down, page_up, page, n_page, page_size_string2) => + view! { + p (class="text-right") { (format!("{} transactions", n_rows.get())) } + div (class="flex flex-row justify-between") { + select (bind:value=page_size_string, + class="p-2 justify-end text-slate-700 dark:text-slate-100 bg-slate-100 dark:bg-slate-800 rounded-md", + id="size-select", + ) { + option (value="20") { "20" } + option (value="10") { "10" } + option (value="30", selected=page_size_string2.get().eq(&Rc::new("30".to_string()))) { "30" } + option (value="40") { "40" } + option (value="50") { "50" } + } + div (class="flex flex-row p-2 bg-slate-200 dark:bg-slate-800 rounded-md") { + button (on:click=page_down,class="m-1 hover:font-bold") { + "<<" + } + div (class="m-1 align-middle text-center") { + (format!("{}/{}",(*page.get() + 1).to_string(), *n_page.get()) ) + } + button (on:click=page_up, class="m-1 hover:font-bold") { + ">>" + } + } + } + })) + (if paginated_data.get().is_some() { + view! { + BaseTable(table_prop.clone()) + } + } else { + view! { + div (class="flex flex-row justify-center") { + Loading() + } + } + }) + } +} diff --git a/client/src/components/the_header.rs b/client/src/components/the_header.rs new file mode 100644 index 0000000..e1aae9b --- /dev/null +++ b/client/src/components/the_header.rs @@ -0,0 +1,18 @@ +use sycamore::prelude::*; + +#[component(TheHeader)] +pub fn the_header(_: ()) -> View { + view! { + "Don't use until global state is recheable from a component" + // header (class="shadow-md h-10 sm:p-2 w-full mb-20 bg-gray-100 dark:bg-slate-500/30 backdrop-blur-lg") { + // nav () { + // div (class="fixed flex justify-between") { + // div (class="font-mono mr-10") { "Fast Insiders" } + // div (class="flex justify-end") { + // button (on:click=toggle_dark_mode, class="mx-1 p-1 bg-pink-200 dark:bg-pink-600 rounded-full") { "toggle dark mode" } + // } + // } + // } + // } + } +} diff --git a/client/src/error_pages.rs b/client/src/error_pages.rs new file mode 100644 index 0000000..d472912 --- /dev/null +++ b/client/src/error_pages.rs @@ -0,0 +1,17 @@ +use perseus::{ErrorPages, Html}; +use sycamore::view; + +pub fn get_error_pages() -> ErrorPages { + let mut error_pages = ErrorPages::new(|url, status, err, _| { + view! { + p { (format!("An error with HTTP code {} occurred at '{}': '{}'.", status, url, err)) } + } + }); + error_pages.add_page(404, |_, _, _, _| { + view! { + p { "Page not found." } + } + }); + + error_pages +} diff --git a/client/src/global_state.rs b/client/src/global_state.rs new file mode 100644 index 0000000..54c8ddb --- /dev/null +++ b/client/src/global_state.rs @@ -0,0 +1,15 @@ +use perseus::{state::GlobalStateCreator, RenderFnResult}; + +pub fn get_global_state_creator() -> GlobalStateCreator { + GlobalStateCreator::new().build_state_fn(get_build_state) +} + +#[perseus::make_rx(AppStateRx)] +pub struct AppState { + pub dark_mode: bool, +} + +#[perseus::autoserde(global_build_state)] +pub async fn get_build_state() -> RenderFnResult { + Ok(AppState { dark_mode: true }) +} diff --git a/client/src/lib.rs b/client/src/lib.rs new file mode 100644 index 0000000..6bad56c --- /dev/null +++ b/client/src/lib.rs @@ -0,0 +1,15 @@ +use perseus::{Html, PerseusApp}; + +mod api; +mod components; +pub mod error_pages; +pub mod global_state; +pub mod templates; + +#[perseus::main] +pub fn main() -> PerseusApp { + PerseusApp::new() + .template(crate::templates::index::get_template) + .global_state_creator(crate::global_state::get_global_state_creator()) + .error_pages(crate::error_pages::get_error_pages) +} diff --git a/client/src/templates/index.rs b/client/src/templates/index.rs new file mode 100644 index 0000000..c7a60df --- /dev/null +++ b/client/src/templates/index.rs @@ -0,0 +1,95 @@ +use std::marker::PhantomData; + +use perseus::{Html, RenderFnResult, RenderFnResultWithCause, SsrNode, Template}; +use sycamore::{ + prelude::{view, View}, + reactive::{cloned, Signal}, +}; + +use crate::{ + api::types::transaction::TransactionCompany, + components::paginated_data_table::{PaginatedTable, PaginatedTableStateRx}, + global_state::AppStateRx, +}; + +#[perseus::make_rx(IndexPageStateRx)] +pub struct IndexPageState { + pub req: String, +} + +#[perseus::template_rx] +pub fn index_page(IndexPageStateRx { req }: IndexPageStateRx, global_state: AppStateRx) -> View { + let dark_mode = global_state.dark_mode; + let dark_mode_2 = dark_mode.clone(); + let dark_mode_3 = dark_mode.clone(); + + let toggle_dark_mode = cloned!(() => move |_| dark_mode_2.set(!*dark_mode.get())); + + let paginated_table_state: PaginatedTableStateRx = PaginatedTableStateRx { + req, + ph_data: Signal::new(PhantomData), + }; + + view! { + main (class=if *dark_mode_3.get() { "dark" } else { "" }) { + link (rel="stylesheet", href = "/.perseus/static/tailwind.css") {} + div (class="bg-slate-200 dark:bg-slate-700 text-slate-700 dark:text-slate-100 font-sans") { + header (class="shadow-md h-12 p-2 align-middle w-full bg-gray-100 dark:bg-slate-500/30 backdrop-blur-lg") { + div (class="flex flex-row justify-between") { + div (class="mr-10 align-middle") { + a (href="/", class="hover:underline") { + "Fast Insiders" + } + } + div (class="align-middle") { + button (on:click=toggle_dark_mode, class="mx-1 py-1 px-2 bg-slate-200 dark:bg-slate-800 rounded-full") + { "Toggle dark mode" } + } + } + } + div (class="flex flex-col items-center justify-center ") { + div (class="w-4/5 m-10 p-3 bg-slate-100 dark:bg-slate-600 rounded-lg items-center justify-center") { + a (class="hover:underline", href="/") { + h1 ( + class="text-center text-lg" + ) { + "Insider Transactions published by the AMF" + } + } + PaginatedTable(paginated_table_state) + } + } + } + } + } +} + +pub fn get_template() -> Template { + Template::new("index") + .build_paths_fn(get_build_paths) + .build_state_fn(get_build_state) + .template(index_page) + .incremental_generation() + .head(head) +} + +#[perseus::head] +pub fn head(_props: IndexPageState) -> View { + view! { + title { "Fast Insiders" } + } +} + +#[perseus::autoserde(build_state)] +pub async fn get_build_state( + path: String, + _locale: String, +) -> RenderFnResultWithCause { + let company_slug: String = path.clone().drain("index".len()..).collect(); + let req = format!("http://localhost:8000/v1/transaction{}", company_slug); + Ok(IndexPageState { req }) +} + +pub async fn get_build_paths() -> RenderFnResult> { + Ok(vec!["".to_string()]) +} diff --git a/client/src/templates/mod.rs b/client/src/templates/mod.rs new file mode 100644 index 0000000..33edc95 --- /dev/null +++ b/client/src/templates/mod.rs @@ -0,0 +1 @@ +pub mod index; diff --git a/client/static/style.css b/client/static/style.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/client/static/style.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/client/static/tailwind.css b/client/static/tailwind.css new file mode 100644 index 0000000..1df2ad2 --- /dev/null +++ b/client/static/tailwind.css @@ -0,0 +1,798 @@ +/* +! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com +*/ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #e5e7eb; + /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +*/ + +html { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + /* 4 */ + font-feature-settings: normal; + /* 5 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font family by default. +2. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ + +[hidden] { + display: none; +} + +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +.static { + position: static; +} + +.fixed { + position: fixed; +} + +.m-2 { + margin: 0.5rem; +} + +.m-1 { + margin: 0.25rem; +} + +.m-10 { + margin: 2.5rem; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.my-2 { + margin-top: 0.5rem; + margin-bottom: 0.5rem; +} + +.mx-1 { + margin-left: 0.25rem; + margin-right: 0.25rem; +} + +.mb-20 { + margin-bottom: 5rem; +} + +.mr-10 { + margin-right: 2.5rem; +} + +.flex { + display: flex; +} + +.table { + display: table; +} + +.h-10 { + height: 2.5rem; +} + +.h-12 { + height: 3rem; +} + +.w-full { + width: 100%; +} + +.w-4\/5 { + width: 80%; +} + +.table-auto { + table-layout: auto; +} + +.transform { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.flex-row { + flex-direction: row; +} + +.flex-col { + flex-direction: column; +} + +.items-center { + align-items: center; +} + +.justify-end { + justify-content: flex-end; +} + +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.rounded-lg { + border-radius: 0.5rem; +} + +.rounded-md { + border-radius: 0.375rem; +} + +.rounded-full { + border-radius: 9999px; +} + +.border { + border-width: 1px; +} + +.border-x { + border-left-width: 1px; + border-right-width: 1px; +} + +.border-b-2 { + border-bottom-width: 2px; +} + +.border-dashed { + border-style: dashed; +} + +.border-slate-500 { + --tw-border-opacity: 1; + border-color: rgb(100 116 139 / var(--tw-border-opacity)); +} + +.bg-slate-200 { + --tw-bg-opacity: 1; + background-color: rgb(226 232 240 / var(--tw-bg-opacity)); +} + +.bg-slate-100 { + --tw-bg-opacity: 1; + background-color: rgb(241 245 249 / var(--tw-bg-opacity)); +} + +.bg-gray-100 { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +.bg-pink-200 { + --tw-bg-opacity: 1; + background-color: rgb(251 207 232 / var(--tw-bg-opacity)); +} + +.p-2 { + padding: 0.5rem; +} + +.p-1 { + padding: 0.25rem; +} + +.p-3 { + padding: 0.75rem; +} + +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + +.px-2 { + padding-left: 0.5rem; + padding-right: 0.5rem; +} + +.text-left { + text-align: left; +} + +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +.align-middle { + vertical-align: middle; +} + +.font-mono { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +.font-sans { + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-slate-700 { + --tw-text-opacity: 1; + color: rgb(51 65 85 / var(--tw-text-opacity)); +} + +.text-indigo-800 { + --tw-text-opacity: 1; + color: rgb(55 48 163 / var(--tw-text-opacity)); +} + +.shadow-md { + --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.backdrop-blur-lg { + --tw-backdrop-blur: blur(16px); + -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); + backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); +} + +.hover\:font-bold:hover { + font-weight: 700; +} + +.hover\:text-indigo-500:hover { + --tw-text-opacity: 1; + color: rgb(99 102 241 / var(--tw-text-opacity)); +} + +.hover\:underline:hover { + text-decoration-line: underline; +} + +.dark .dark\:bg-slate-800 { + --tw-bg-opacity: 1; + background-color: rgb(30 41 59 / var(--tw-bg-opacity)); +} + +.dark .dark\:bg-slate-500\/30 { + background-color: rgb(100 116 139 / 0.3); +} + +.dark .dark\:bg-pink-600 { + --tw-bg-opacity: 1; + background-color: rgb(219 39 119 / var(--tw-bg-opacity)); +} + +.dark .dark\:bg-slate-700 { + --tw-bg-opacity: 1; + background-color: rgb(51 65 85 / var(--tw-bg-opacity)); +} + +.dark .dark\:bg-slate-600 { + --tw-bg-opacity: 1; + background-color: rgb(71 85 105 / var(--tw-bg-opacity)); +} + +.dark .dark\:text-slate-100 { + --tw-text-opacity: 1; + color: rgb(241 245 249 / var(--tw-text-opacity)); +} + +.dark .dark\:text-indigo-300 { + --tw-text-opacity: 1; + color: rgb(165 180 252 / var(--tw-text-opacity)); +} + +.dark .dark\:hover\:text-indigo-600:hover { + --tw-text-opacity: 1; + color: rgb(79 70 229 / var(--tw-text-opacity)); +} + +@media (min-width: 640px) { + .sm\:p-2 { + padding: 0.5rem; + } +} diff --git a/client/tailwind.config.js b/client/tailwind.config.js new file mode 100644 index 0000000..60aa925 --- /dev/null +++ b/client/tailwind.config.js @@ -0,0 +1,4 @@ +module.exports = { + darkMode: 'class', + content: ["./src/**/*.rs", "./index.html"], +}; diff --git a/makefile b/makefile new file mode 100644 index 0000000..740de7f --- /dev/null +++ b/makefile @@ -0,0 +1,17 @@ +include .env + +# Migrations should be written first and the model files can be created using this command +db_entities: + cd server && \ + sea-orm-cli generate entity --database-url $(DATABASE_URL) -o src/model --with-serde both + +server-dev: + cargo run --bin server + +tailwind: + cd client && \ + tailwindcss -i static/style.css -o static/tailwind.css -w + +serve: + cd client && \ + perseus serve -w diff --git a/server/Cargo.toml b/server/Cargo.toml new file mode 100644 index 0000000..ea850b0 --- /dev/null +++ b/server/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "server" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +migration = { version = "0.1.0", path = "./migration" } +chrono = { workspace = true, features = ["serde"] } +perseus = { version = "0.3.6", features = ["hydrate"] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +dotenvy = { workspace = true } +envy = { workspace = true } +tokio = { version = "^1.20.1", features = ["full"] } +reqwest = { version = "0.11", features = ["json"] } +rocket = { version = "0.5.0-rc.2", features = ["json"] } +sea-orm = { version = "0.10.7", features = [ + "runtime-tokio-rustls", + "macros", + "sqlx-mysql", +] } +lopdf = "0.29.0" +bytes = { version = "1.3.0", features = ["serde"] } +lazy_static = "1.4.0" +pretty_env_logger = "0.4.0" +log = "0.4.17" +futures = "0.3.25" +rocket_contrib = "0.4.11" +async-trait = "0.1.61" +sea-orm-rocket = "0.5.2" +thiserror = "1.0.38" +sea-query = "^0.27.1" +slug = "0.1.4" diff --git a/server/migration/.gitignore b/server/migration/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/server/migration/.gitignore @@ -0,0 +1 @@ +/target diff --git a/server/migration/Cargo.lock b/server/migration/Cargo.lock new file mode 100644 index 0000000..0e8a85d --- /dev/null +++ b/server/migration/Cargo.lock @@ -0,0 +1,2188 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + +[[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 = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "async-channel" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", + "tokio", +] + +[[package]] +name = "async-io" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" +dependencies = [ + "async-lock", + "autocfg", + "concurrent-queue", + "futures-lite", + "libc", + "log", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "windows-sys", +] + +[[package]] +name = "async-lock" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +dependencies = [ + "event-listener", + "futures-lite", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-attributes", + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-task" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + +[[package]] +name = "async-trait" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "705339e0e4a9690e2908d2b3d049d85682cf19fbd5782494498fbf7003a6a282" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atoi" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic-waker" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bae" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b8de67cc41132507eeece2584804efcb15f85ba516e34c944b7667f480397a" +dependencies = [ + "heck 0.3.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + +[[package]] +name = "base64ct" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", +] + +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" + +[[package]] +name = "cc" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "num-integer", + "num-traits", + "winapi", +] + +[[package]] +name = "clap" +version = "3.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "concurrent-queue" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" + +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "cxx" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d1075c37807dcf850c379432f0df05ba52cc30f279c5cfc43cc221ce7f8579" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5044281f61b27bc598f2f6647d480aed48d2bf52d6eb0b627d84c0361b17aa70" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b50bc93ba22c27b0d31128d2d130a0a6b3d267ae27ef7e4fae2167dfe8781c" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e61fda7e62115119469c7b3591fd913ecca96fb766cfd3f2e2502ab7bc87a5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", + "crypto-bigint", + "pem-rfc7468", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dotenvy" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d8c417d7a8cb362e0c37e5d815f5eb7c37f79ff93707329d5a194e42e54ca0" + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" + +[[package]] +name = "futures-executor" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" + +[[package]] +name = "futures-task" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" + +[[package]] +name = "futures-util" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gloo-timers" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98c4a8d6391675c6b2ee1a6c8d06e8e2d03605c44cec1270675985a4c2a5500b" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", + "value-bag", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "migration" +version = "0.1.0" +dependencies = [ + "async-std", + "sea-orm-migration", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "mio" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + +[[package]] +name = "nom" +version = "7.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5507769c4919c998e69e49c839d9dc6e693ede4cc4290d6ad8b41d4f09c548c" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "ouroboros" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbb50b356159620db6ac971c6d5c9ab788c9cc38a6f49619fca2a27acb062ca" +dependencies = [ + "aliasable", + "ouroboros_macro", +] + +[[package]] +name = "ouroboros_macro" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0d9d1a6191c4f391f87219d1ea42b23f09ee84d64763cd05ee6ea88d9f384d" +dependencies = [ + "Inflector", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "paste" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" + +[[package]] +name = "pem-rfc7468" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01de5d978f34aa4b2296576379fcc416034702fd94117c56ffd8a1a767cefb30" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a78f66c04ccc83dd4486fd46c33896f4e17b24a7a3a6400dedc48ed0ddd72320" +dependencies = [ + "der", + "pkcs8", + "zeroize", +] + +[[package]] +name = "pkcs8" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +dependencies = [ + "der", + "spki", + "zeroize", +] + +[[package]] +name = "polling" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "windows-sys", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[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", + "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-macro2" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +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 = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rsa" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" +dependencies = [ + "byteorder", + "digest", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "smallvec", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls" +version = "0.20.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64", +] + +[[package]] +name = "rustversion" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sea-orm" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc2db217f2061ab2bbb1bd22323a533ace0617f97690919f3ed3894e1b3ba170" +dependencies = [ + "async-stream", + "async-trait", + "futures", + "futures-util", + "log", + "ouroboros", + "sea-orm-macros", + "sea-query", + "sea-query-binder", + "sea-strum", + "serde", + "sqlx", + "thiserror", + "tracing", + "url", +] + +[[package]] +name = "sea-orm-cli" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcce92f0f804acd10b4378a3c8b0e5fb28f3a9ae9337006bd651baa3a95632c" +dependencies = [ + "chrono", + "clap", + "dotenvy", + "regex", + "sea-schema", + "tracing", + "tracing-subscriber", + "url", +] + +[[package]] +name = "sea-orm-macros" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38066057ef1fa17ddc6ce1458cf269862b8f1df919497d110ea127b549a90fbd" +dependencies = [ + "bae", + "heck 0.3.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sea-orm-migration" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada716f9825e4190a0a8ebaecbf7171ce0ed6f218ea2e70086bdc72ccfc1d03c" +dependencies = [ + "async-trait", + "clap", + "dotenvy", + "sea-orm", + "sea-orm-cli", + "sea-schema", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "sea-query" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f0fc4d8e44e1d51c739a68d336252a18bc59553778075d5e32649be6ec92ed" +dependencies = [ + "sea-query-derive", +] + +[[package]] +name = "sea-query-binder" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2585b89c985cfacfe0ec9fc9e7bb055b776c1a2581c4e3c6185af2b8bf8865" +dependencies = [ + "sea-query", + "sqlx", +] + +[[package]] +name = "sea-query-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cdc022b4f606353fe5dc85b09713a04e433323b70163e81513b141c6ae6eb5" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn", + "thiserror", +] + +[[package]] +name = "sea-schema" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d5fda574d980e9352b6c7abd6fc75697436fe0078cac2b548559b52643ad3b" +dependencies = [ + "futures", + "sea-query", + "sea-schema-derive", +] + +[[package]] +name = "sea-schema-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56821b7076f5096b8f726e2791ad255a99c82498e08ec477a65a96c461ff1927" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sea-strum" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391d06a6007842cfe79ac6f7f53911b76dfd69fc9a6769f1cf6569d12ce20e1b" +dependencies = [ + "sea-strum_macros", +] + +[[package]] +name = "sea-strum_macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b4397b825df6ccf1e98bcdabef3bbcfc47ff5853983467850eeab878384f21" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "slab" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spki" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlformat" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9249290c05928352f71c077cc44a464d880c63f26f7534728cca008e135c0428" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" +dependencies = [ + "ahash", + "atoi", + "bitflags", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "digest", + "dotenvy", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-util", + "generic-array", + "hashlink", + "hex", + "indexmap", + "itoa", + "libc", + "log", + "memchr", + "num-bigint", + "once_cell", + "paste", + "percent-encoding", + "rand", + "rsa", + "rustls", + "rustls-pemfile", + "sha1", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "webpki-roots", +] + +[[package]] +name = "sqlx-macros" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b850fa514dc11f2ee85be9d055c512aa866746adfacd1cb42d867d68e6a5b0d9" +dependencies = [ + "dotenvy", + "either", + "heck 0.4.0", + "once_cell", + "proc-macro2", + "quote", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9f76183f91ecfb55e1d7d5602bd1d979e38a3a522fe900241cf195624d67ae" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "windows-sys", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-stream" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "value-bag" +version = "1.0.0-alpha.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" +dependencies = [ + "ctor", + "version_check", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[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.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] +name = "web-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" diff --git a/server/migration/Cargo.toml b/server/migration/Cargo.toml new file mode 100644 index 0000000..6d3180b --- /dev/null +++ b/server/migration/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "migration" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "migration" +path = "src/lib.rs" + +[dependencies] +async-std = { version = "^1", features = ["attributes", "tokio1"] } + +[dependencies.sea-orm-migration] +version = "^0.10.0" +features = [ +"sqlx-mysql", +"runtime-tokio-rustls", +] diff --git a/server/migration/README.md b/server/migration/README.md new file mode 100644 index 0000000..b3ea53e --- /dev/null +++ b/server/migration/README.md @@ -0,0 +1,41 @@ +# Running Migrator CLI + +- Generate a new migration file + ```sh + cargo run -- migrate generate MIGRATION_NAME + ``` +- Apply all pending migrations + ```sh + cargo run + ``` + ```sh + cargo run -- up + ``` +- Apply first 10 pending migrations + ```sh + cargo run -- up -n 10 + ``` +- Rollback last applied migrations + ```sh + cargo run -- down + ``` +- Rollback last 10 applied migrations + ```sh + cargo run -- down -n 10 + ``` +- Drop all tables from the database, then reapply all migrations + ```sh + cargo run -- fresh + ``` +- Rollback all applied migrations, then reapply all migrations + ```sh + cargo run -- refresh + ``` +- Rollback all applied migrations + ```sh + cargo run -- reset + ``` +- Check the status of all migrations + ```sh + cargo run -- status + ``` diff --git a/server/migration/src/lib.rs b/server/migration/src/lib.rs new file mode 100644 index 0000000..86bb294 --- /dev/null +++ b/server/migration/src/lib.rs @@ -0,0 +1,18 @@ +pub use sea_orm_migration::prelude::*; + +mod m20230112_115856_create_company_table; +mod m20230112_160440_create_transaction_table; +mod m20230119_112539_create_transactions_in_process_table; + +pub struct Migrator; + +#[async_trait::async_trait] +impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + vec![ + Box::new(m20230112_115856_create_company_table::Migration), + Box::new(m20230112_160440_create_transaction_table::Migration), + Box::new(m20230119_112539_create_transactions_in_process_table::Migration), + ] + } +} diff --git a/server/migration/src/m20230112_115856_create_company_table.rs b/server/migration/src/m20230112_115856_create_company_table.rs new file mode 100644 index 0000000..9bbc62f --- /dev/null +++ b/server/migration/src/m20230112_115856_create_company_table.rs @@ -0,0 +1,52 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(Company::Table) + .if_not_exists() + .col( + ColumnDef::new(Company::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col( + ColumnDef::new(Company::Slug) + .string() + .unique_key() + .not_null(), + ) + .col( + ColumnDef::new(Company::Name) + .string() + .unique_key() + .not_null(), + ) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(Company::Table).to_owned()) + .await + } +} + +/// Learn more at https://docs.rs/sea-query#iden +#[derive(Iden)] +pub enum Company { + Table, + Id, + Slug, + Name, +} diff --git a/server/migration/src/m20230112_160440_create_transaction_table.rs b/server/migration/src/m20230112_160440_create_transaction_table.rs new file mode 100644 index 0000000..0c71220 --- /dev/null +++ b/server/migration/src/m20230112_160440_create_transaction_table.rs @@ -0,0 +1,78 @@ +use crate::m20230112_115856_create_company_table as company; +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(Transaction::Table) + .if_not_exists() + .col( + ColumnDef::new(Transaction::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(Transaction::CompanyId).integer().not_null()) + .col( + ColumnDef::new(Transaction::ForeignId) + .string() + .not_null() + .unique_key(), + ) + .col(ColumnDef::new(Transaction::DatePublished).date().not_null()) + .col(ColumnDef::new(Transaction::DateExecuted).date().not_null()) + .col(ColumnDef::new(Transaction::Person).text().not_null()) + .col(ColumnDef::new(Transaction::Exchange).string().not_null()) + .col(ColumnDef::new(Transaction::Nature).string().not_null()) + .col(ColumnDef::new(Transaction::Isin).string()) + .col(ColumnDef::new(Transaction::Instrument).string().not_null()) + .col(ColumnDef::new(Transaction::Volume).integer().not_null()) + .col(ColumnDef::new(Transaction::UnitPrice).float().not_null()) + .to_owned(), + ) + .await?; + + manager + .create_foreign_key( + ForeignKey::create() + .name("FK_transaction_to_company") + .from(Transaction::Table, Transaction::CompanyId) + .to(company::Company::Table, company::Company::Id) + .on_update(ForeignKeyAction::Cascade) + .on_delete(ForeignKeyAction::Cascade) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(Transaction::Table).to_owned()) + .await + } +} + +/// Learn more at https://docs.rs/sea-query#iden +#[derive(Iden)] +enum Transaction { + Table, + Id, + CompanyId, + ForeignId, + DatePublished, + DateExecuted, + Person, + Exchange, + Nature, + Isin, + Instrument, + Volume, + UnitPrice, +} diff --git a/server/migration/src/m20230119_112539_create_transactions_in_process_table.rs b/server/migration/src/m20230119_112539_create_transactions_in_process_table.rs new file mode 100644 index 0000000..8963058 --- /dev/null +++ b/server/migration/src/m20230119_112539_create_transactions_in_process_table.rs @@ -0,0 +1,66 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(InProcessTransaction::Table) + .if_not_exists() + .col( + ColumnDef::new(InProcessTransaction::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col( + ColumnDef::new(InProcessTransaction::CreatedAt) + .date_time() + .not_null(), + ) + .col( + ColumnDef::new(InProcessTransaction::ForeignId) + .string() + .unique_key() + .not_null(), + ) + .col( + ColumnDef::new(InProcessTransaction::DocPath) + .string() + .unique_key() + .not_null(), + ) + .col( + ColumnDef::new(InProcessTransaction::Failed) + .boolean() + .not_null(), + ) + .col(ColumnDef::new(InProcessTransaction::ErrorString).text()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(InProcessTransaction::Table).to_owned()) + .await + } +} + +/// Learn more at https://docs.rs/sea-query#iden +#[derive(Iden)] +enum InProcessTransaction { + Table, + Id, + CreatedAt, + ForeignId, + DocPath, + Failed, + ErrorString, +} diff --git a/server/migration/src/main.rs b/server/migration/src/main.rs new file mode 100644 index 0000000..c6b6e48 --- /dev/null +++ b/server/migration/src/main.rs @@ -0,0 +1,6 @@ +use sea_orm_migration::prelude::*; + +#[async_std::main] +async fn main() { + cli::run_cli(migration::Migrator).await; +} diff --git a/server/src/amf/mod.rs b/server/src/amf/mod.rs new file mode 100644 index 0000000..d917625 --- /dev/null +++ b/server/src/amf/mod.rs @@ -0,0 +1,11 @@ +use crate::amf::types::transaction_data::TransactionData; + +pub mod service; +pub mod types; + +#[async_trait::async_trait] +pub trait TransactionDataTrait { + type Err; + + async fn get_transaction_data(self: &Self) -> Result; +} diff --git a/server/src/amf/service/amf_response.rs b/server/src/amf/service/amf_response.rs new file mode 100644 index 0000000..772b0ca --- /dev/null +++ b/server/src/amf/service/amf_response.rs @@ -0,0 +1,66 @@ +use crate::{ + amf::{ + types::{ + amf_response::{Document, Hit}, + AMFResponse, TransactionData, + }, + TransactionDataTrait, + }, + task::get_amf_transactions::GetAMFTransactionsError, +}; + +use super::pdf::AMFPdf; + +impl AMFResponse { + pub fn get_hits(&self) -> &Vec { + &self.hits.hits + } +} + +#[async_trait::async_trait] +impl TransactionDataTrait for Hit { + type Err = GetAMFTransactionsError; + async fn get_transaction_data(self: &Self) -> Result { + let foreign_id = self.source.numero.to_owned(); + let docs = self.get_documents(); + if docs.len() > 1 { + warn!("Transaction number {} contains more than one document, only the first document will be parsed for information", foreign_id); + } + + let doc_path = &docs + .first() + .ok_or(GetAMFTransactionsError::NoDocumentError( + foreign_id.to_owned(), + ))? + .path; + + let amf_pdf = AMFPdf::new(&doc_path); + let info = amf_pdf.extract_info().await.map_err(|e| { + GetAMFTransactionsError::InformationExtractionError(doc_path.to_string(), e) + })?; + + Ok(TransactionData { + foreign_id, + company_name: info.company_name, + isin: info.isin, + person: info.person, + date_published: info.date_published, + date_executed: info.date_executed, + exchange: info.exchange, + nature: info.nature, + instrument: info.instrument, + volume: info.volume, + unit_price: info.unit_price, + }) + } +} + +impl Hit { + pub fn get_documents(&self) -> &Vec { + &self.source.documents + } + + pub fn get_foreign_id(&self) -> String { + self.source.numero.to_owned() + } +} diff --git a/server/src/amf/service/information_req.rs b/server/src/amf/service/information_req.rs new file mode 100644 index 0000000..b182c1a --- /dev/null +++ b/server/src/amf/service/information_req.rs @@ -0,0 +1,60 @@ +use std::fmt; +use thiserror::Error; + +use crate::amf::types::AMFResponse; +use crate::CONFIG; + +#[derive(Debug, Error)] +pub enum AMFRequestError { + #[error("Request error: {0}")] + RequestError(reqwest::Error), + #[error("Json conversion error: {0}")] + JsonConversionError(reqwest::Error), + #[error("Status code error: {0}")] + StatusCodeError(reqwest::Error), +} + +pub struct AMFRequest { + url: String, +} + +impl AMFRequest { + pub fn new(inf_type: AMFRequestType, from: u32, size: u32) -> Self { + let url = CONFIG + .amf_informations_req + .replace("{{inf_type}}", &inf_type.to_string()) + .replace("{{from}}", &from.to_string()) + .replace("{{size}}", &size.to_string()); + + AMFRequest { url } + } + + pub async fn get_list(&self) -> Result { + Ok(reqwest::get(&self.url) + .await + .map_err(|e| AMFRequestError::RequestError(e))? + .error_for_status() + .map_err(|e| AMFRequestError::StatusCodeError(e))? + .json::() + .await + .map_err(|e| AMFRequestError::JsonConversionError(e))?) + } +} + +pub enum AMFRequestType { + DD, +} + +impl Default for AMFRequestType { + fn default() -> Self { + AMFRequestType::DD + } +} + +impl fmt::Display for AMFRequestType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AMFRequestType::DD => write!(f, "DD"), + } + } +} diff --git a/server/src/amf/service/mod.rs b/server/src/amf/service/mod.rs new file mode 100644 index 0000000..ae38c0a --- /dev/null +++ b/server/src/amf/service/mod.rs @@ -0,0 +1,6 @@ +pub mod amf_response; +pub mod information_req; +pub mod pdf; + +#[cfg(test)] +mod test; diff --git a/server/src/amf/service/pdf.rs b/server/src/amf/service/pdf.rs new file mode 100644 index 0000000..34cd5d0 --- /dev/null +++ b/server/src/amf/service/pdf.rs @@ -0,0 +1,237 @@ +use bytes::Bytes; +use chrono::NaiveDate; +use std::num::ParseFloatError; +use thiserror::Error; + +use crate::amf::types::date::naive_date_from_str; +use crate::amf::types::date::DateParseError; +use crate::CONFIG; + +#[derive(Debug, Clone)] +pub struct AMFPdf { + url: String, +} + +#[derive(Debug, Error)] +pub enum PatternExtractionError { + #[error("Person not found")] + PersonNotFoundError, + #[error("Date executed not found")] + DateExecutedNotFoundError, + #[error("Date published not found")] + DatePublishedNotFoundError, + #[error("Exchange not found")] + ExchangeNotFoundError, + #[error("Nature not found")] + NatureNotFoundError, + #[error("Instrument not found")] + InstrumentNotFoundError, + #[error("Coordonnees section not found")] + CoordonneesNotFound, + #[error("Company name not found")] + CompanyNameNotFound, + #[error("Aggregated informations not found")] + AggregatedInformationNotFoundError, + #[error("Volume not found")] + VolumeNotFoundError, + #[error("Price not found")] + PriceNotFoundError, +} + +#[derive(Debug, Error)] +pub enum AMFPdfError { + #[error("Download error: {0}")] + DownloadError(reqwest::Error), + #[error("Bytes conversion error: {0}")] + BytesConversionError(reqwest::Error), + #[error("Error loading pdf document: {0}")] + DocumentLoadError(lopdf::Error), + #[error("Error during lopdf text extraction: {0}")] + PdfTextExtractionError(lopdf::Error), + #[error("Error during extraction of information: {0}")] + PatternExtractionError(PatternExtractionError), + #[error("Error parsing date: {0}")] + DateParseError(DateParseError), + #[error("Error parsing unit price: {0}")] + PriceParseError(ParseFloatError), + #[error("Error parsing volume: {0}")] + VolumeParseError(ParseFloatError), +} + +pub struct AMFPdfData { + pub company_name: String, + pub isin: Option, + pub person: String, + pub date_published: NaiveDate, + pub date_executed: NaiveDate, + pub exchange: String, + pub nature: String, + pub instrument: String, + pub volume: f32, + pub unit_price: f32, +} + +impl AMFPdf { + pub fn new(path: &String) -> AMFPdf { + let mut url = (&CONFIG.amf_documents_path).to_string(); + url.push_str(&path); + AMFPdf { url } + } + + async fn download(&self) -> Result { + Ok(reqwest::get(&self.url) + .await + .map_err(|e| AMFPdfError::DownloadError(e))? + .bytes() + .await + .map_err(|e| AMFPdfError::BytesConversionError(e))?) + } + + async fn extract_text(&self) -> Result { + let bfile = self.download().await?; + let pdf = + lopdf::Document::load_mem(&bfile).map_err(|e| AMFPdfError::DocumentLoadError(e))?; + let mut text = "".to_string(); + for (idx, _) in pdf.page_iter().enumerate() { + text.push_str( + &pdf.extract_text(&[idx as u32 + 1]) + .map_err(|e| AMFPdfError::PdfTextExtractionError(e))?, + ); + } + Ok(text) + } + + pub async fn extract_info(&self) -> Result { + let mut text = self.extract_text().await?; + debug!("Extracted text from document:\n{}", text); + + let isin = extract_pattern( + &text, + "CODE D’IDENTIFICATION DE L’INSTRUMENT FINANCIER : ", + "\n", + ) + .map_or_else( + || { + Some( + text.lines() + .skip_while(|l| l.is_empty()) + .nth(1) + .unwrap() + .split(" ") + .next() + .unwrap() + .get(0..12) + .map(|t| t.to_string()), + ) + }, + |t| Some(Some(t.get(0..12).unwrap_or(&t).to_string())), + ) + .unwrap_or(None); + + let person = extract_pattern( + &text, + &"NOM /FONCTION DE LA PERSONNE EXERCANT DES RESPONSABILITES DIRIGEANTES OU DE LAPERSONNE ETROITEMENT LIEE :\n", + "\n", + ) + .ok_or(AMFPdfError::PatternExtractionError( + PatternExtractionError::PersonNotFoundError, + ))?; + + let date_published_raw = + extract_pattern(&text, &"DATE DE RECEPTION DE LA NOTIFICATION : ", &"\n").ok_or( + AMFPdfError::PatternExtractionError( + PatternExtractionError::DatePublishedNotFoundError, + ), + )?; + + let date_published = + naive_date_from_str(&date_published_raw).map_err(|e| AMFPdfError::DateParseError(e))?; + + let date_executed_raw = extract_pattern(&text, &"DATE DE LA TRANSACTION : ", &"\n").ok_or( + AMFPdfError::PatternExtractionError(PatternExtractionError::DateExecutedNotFoundError), + )?; + + let date_executed = + naive_date_from_str(&date_executed_raw).map_err(|e| AMFPdfError::DateParseError(e))?; + + let exchange = extract_pattern(&text, &"LIEU DE LA TRANSACTION : ", &"\n").ok_or( + AMFPdfError::PatternExtractionError(PatternExtractionError::ExchangeNotFoundError), + )?; + + let nature = extract_pattern(&text, &"NATURE DE LA TRANSACTION : ", &"\n").ok_or( + AMFPdfError::PatternExtractionError(PatternExtractionError::NatureNotFoundError), + )?; + + let instrument = extract_pattern(&text, &"DESCRIPTION DE L’INSTRUMENT FINANCIER : ", &"\n") + .ok_or(AMFPdfError::PatternExtractionError( + PatternExtractionError::InstrumentNotFoundError, + ))?; + + let inf_coordonnees = + text.find("COORDONNEES DE L’EMETTEUR") + .ok_or(AMFPdfError::PatternExtractionError( + PatternExtractionError::CoordonneesNotFound, + ))?; + + let mut text_cp = text.clone(); + text_cp.drain(0..inf_coordonnees); + + let company_name = extract_pattern(&text_cp, &"NOM : ", &"\n").ok_or( + AMFPdfError::PatternExtractionError(PatternExtractionError::CompanyNameNotFound), + )?; + + let inf_aggregees_idx = + text.find("INFORMATIONS AGREGEES") + .ok_or(AMFPdfError::PatternExtractionError( + PatternExtractionError::AggregatedInformationNotFoundError, + ))?; + + text.drain(0..inf_aggregees_idx); + + let volume = extract_pattern(&text, &"VOLUME : ", &"\n") + .ok_or(AMFPdfError::PatternExtractionError( + PatternExtractionError::VolumeNotFoundError, + ))? + .replace(" ", "") + .parse::() + .map_err(|e| AMFPdfError::VolumeParseError(e))?; + + let unit_price = extract_pattern(&text, &"PRIX : ".to_string(), &"\n".to_string()) + .ok_or(AMFPdfError::PatternExtractionError( + PatternExtractionError::PriceNotFoundError, + ))? + .replace(" ", "") + .chars() + .take_while(|c| c.is_digit(10) || c == &'.') + .collect::() + .parse::() + .map_err(|e| AMFPdfError::PriceParseError(e))?; + + Ok(AMFPdfData { + company_name, + isin, + person, + date_published, + date_executed, + exchange, + nature, + instrument, + volume, + unit_price, + }) + } +} + +fn extract_pattern(s: &String, p1: &str, p2: &str) -> Option { + let idx1 = s.find(p1)?; + + let idx2 = s + .get(idx1 + p1.len()..) + .unwrap() + .find(p2) + .unwrap_or(s.len()) + + idx1 + + p1.len(); + + Some(s.get(idx1 + p1.len()..idx2).unwrap().to_string()) +} diff --git a/server/src/amf/service/test/amf_response.rs b/server/src/amf/service/test/amf_response.rs new file mode 100644 index 0000000..eb8aced --- /dev/null +++ b/server/src/amf/service/test/amf_response.rs @@ -0,0 +1,18 @@ +use crate::amf::service::information_req::{AMFRequest, AMFRequestType}; + +/// This function will make sure that only one document is given by the AMF API in the last 100 +/// records. The program will need a change otherwise. +#[tokio::test] +async fn insure_single_document_per_hit() { + dotenvy::dotenv().expect("Failed to load .env file"); + + let req = AMFRequest::new(AMFRequestType::DD, 0, 100) + .get_list() + .await + .expect("AMF Endpoint should be available"); + + for hit in req.get_hits() { + let n_docs = hit.get_documents().len(); + assert_eq!(n_docs, 1); + } +} diff --git a/server/src/amf/service/test/mod.rs b/server/src/amf/service/test/mod.rs new file mode 100644 index 0000000..e3bc3b0 --- /dev/null +++ b/server/src/amf/service/test/mod.rs @@ -0,0 +1,2 @@ +mod amf_response; +mod pdf; diff --git a/server/src/amf/service/test/pdf.rs b/server/src/amf/service/test/pdf.rs new file mode 100644 index 0000000..0a5fb10 --- /dev/null +++ b/server/src/amf/service/test/pdf.rs @@ -0,0 +1,35 @@ +use futures::StreamExt; + +use crate::{ + amf::service::{ + information_req::{AMFRequest, AMFRequestType}, + pdf::AMFPdf, + }, + env, logger, +}; + +#[tokio::test] +async fn read_data_from_last_100_amf_pdf() { + env::load_env().expect("Failed to load .env"); + logger::init_log().expect("Failed to init log"); + + let size = 100; + let req = AMFRequest::new(AMFRequestType::DD, 1, size) + .get_list() + .await + .expect("AMF Endpoint should be available"); + + let mut futures = Vec::new(); + for hit in req.get_hits().iter() { + let doc_path = &hit.get_documents()[0].path; + + futures.push(async move { AMFPdf::new(doc_path).clone().extract_info().await }); + } + + let stream = futures::stream::iter(futures).buffer_unordered(10); + let results = stream.collect::>().await; + + for res in results { + assert!(res.is_ok()); + } +} diff --git a/server/src/amf/types/amf_response.rs b/server/src/amf/types/amf_response.rs new file mode 100644 index 0000000..ccd1779 --- /dev/null +++ b/server/src/amf/types/amf_response.rs @@ -0,0 +1,187 @@ +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AMFResponse { + pub hits: Hits, + pub aggregations: Aggregations, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Hits { + pub total: Total, + pub hits: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Total { + pub value: i64, + pub relation: String, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Hit { + #[serde(rename = "_ignored")] + pub ignored: Option>, + #[serde(rename = "_source")] + pub source: Source, + pub sort: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Source { + pub date_creation: String, + #[serde(rename = "numeroSOIF")] + pub numero_soif: Value, + pub numero: String, + pub types_operation: Vec, + pub documents: Vec, + pub titre: Value, + pub date_publication: String, + pub role_regulateur: String, + pub marche: Value, + pub index_year: i64, + pub sous_type_document: Value, + pub date_action: Value, + pub id: i64, + pub instrument_financier: Value, + pub numero_concatene: String, + pub domaine: String, + pub types_document: Vec, + pub types_information: Vec, + pub date_mise_en_ligne: String, + pub date_information: String, + pub langue: String, + pub version: i64, + pub regulateur: String, + pub relations: Vec, + pub societes: Vec, + pub annee_comptable: Value, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Document { + pub accessible: bool, + pub issuer_id: Option, + pub path: String, + pub numero: Value, + pub signature: Option, + pub format: Value, + pub details: Details, + pub doc_regulateur: bool, + pub nom_fichier: String, + pub date_reception: Value, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Details { + pub date: String, + #[serde(rename = "content_type")] + pub content_type: String, + pub language: String, + pub title: String, + #[serde(rename = "content_length")] + pub content_length: i64, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Societe { + pub role: String, + pub raison_sociale: String, + pub jeton: String, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Aggregations { + pub types_information: TypesInformation, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TypesInformation { + #[serde(rename = "doc_count_error_upper_bound")] + pub doc_count_error_upper_bound: i64, + #[serde(rename = "sum_other_doc_count")] + pub sum_other_doc_count: i64, + pub buckets: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Bucket { + pub key: String, + #[serde(rename = "doc_count")] + pub doc_count: i64, + pub types_operation: TypesOperation, + pub types_document: TypesDocument, + pub instrument_financier: InstrumentFinancier, + pub marche: Marche, + pub annee_comptable: AnneeComptable, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TypesOperation { + #[serde(rename = "doc_count_error_upper_bound")] + pub doc_count_error_upper_bound: i64, + #[serde(rename = "sum_other_doc_count")] + pub sum_other_doc_count: i64, + pub buckets: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TypesDocument { + #[serde(rename = "doc_count_error_upper_bound")] + pub doc_count_error_upper_bound: i64, + #[serde(rename = "sum_other_doc_count")] + pub sum_other_doc_count: i64, + pub buckets: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Bucket2 { + pub key: String, + #[serde(rename = "doc_count")] + pub doc_count: i64, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InstrumentFinancier { + #[serde(rename = "doc_count_error_upper_bound")] + pub doc_count_error_upper_bound: i64, + #[serde(rename = "sum_other_doc_count")] + pub sum_other_doc_count: i64, + pub buckets: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Marche { + #[serde(rename = "doc_count_error_upper_bound")] + pub doc_count_error_upper_bound: i64, + #[serde(rename = "sum_other_doc_count")] + pub sum_other_doc_count: i64, + pub buckets: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AnneeComptable { + #[serde(rename = "doc_count_error_upper_bound")] + pub doc_count_error_upper_bound: i64, + #[serde(rename = "sum_other_doc_count")] + pub sum_other_doc_count: i64, + pub buckets: Vec, +} diff --git a/server/src/amf/types/date.rs b/server/src/amf/types/date.rs new file mode 100644 index 0000000..96669d7 --- /dev/null +++ b/server/src/amf/types/date.rs @@ -0,0 +1,93 @@ +use chrono::Month; +use chrono::NaiveDate; +use std::fmt; +use std::num::ParseIntError; +use std::str::FromStr; + +struct FrenchMonth(Month); +#[derive(Debug)] +pub enum FrenchMonthParseError { + UnknownMonth(String), +} + +impl fmt::Display for FrenchMonthParseError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +impl std::error::Error for FrenchMonthParseError {} + +impl FromStr for FrenchMonth { + type Err = FrenchMonthParseError; + fn from_str(s: &str) -> Result { + match s.to_ascii_lowercase().as_str() { + "janvier" => Ok(FrenchMonth(Month::January)), + "fevrier" => Ok(FrenchMonth(Month::February)), + "février" => Ok(FrenchMonth(Month::February)), + "mars" => Ok(FrenchMonth(Month::March)), + "avril" => Ok(FrenchMonth(Month::April)), + "mai" => Ok(FrenchMonth(Month::May)), + "juin" => Ok(FrenchMonth(Month::June)), + "juillet" => Ok(FrenchMonth(Month::July)), + "aout" => Ok(FrenchMonth(Month::August)), + "août" => Ok(FrenchMonth(Month::August)), + "septembre" => Ok(FrenchMonth(Month::September)), + "octobre" => Ok(FrenchMonth(Month::October)), + "novembre" => Ok(FrenchMonth(Month::November)), + "decembre" => Ok(FrenchMonth(Month::December)), + "décembre" => Ok(FrenchMonth(Month::December)), + s => Err(FrenchMonthParseError::UnknownMonth(s.to_string())), + } + } +} + +#[derive(Debug)] +pub enum DateParseError { + NotEnoughData(String), + DayParseError(ParseIntError), + MonthParseError(FrenchMonthParseError), + YearParseError(ParseIntError), + InvalidDateError(String), +} + +impl fmt::Display for DateParseError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +impl std::error::Error for DateParseError {} + +/// This function will return a chrono naive date from an input with the following format: +/// Day month and year are separated by 1 space and are written exactly in that order. +/// The day and years are represented by numbers while the month is represented by its french name. +pub fn naive_date_from_str(s: &str) -> Result { + let mut data = s.split(" "); + let day = data.next().ok_or(DateParseError::NotEnoughData( + "Given date string is empty".to_string(), + ))?; + let month = data.next().ok_or(DateParseError::NotEnoughData(format!( + "Given date string: \"{s}\" does not contain a complete date" + )))?; + let year = data.next().ok_or(DateParseError::NotEnoughData(format!( + "Given date string: \"{s}\" does not contain a complete date" + )))?; + + let date = NaiveDate::from_ymd_opt( + year.parse() + .map_err(|e| DateParseError::YearParseError(e))?, + month + .parse::() + .map_err(|e| DateParseError::MonthParseError(e))? + .0 as u32 + + 1, + day.parse().map_err(|e| DateParseError::DayParseError(e))?, + ) + .ok_or(DateParseError::InvalidDateError(format!( + "Invalid date resulted from string {}", + s + )))?; + + Ok(date) +} diff --git a/server/src/amf/types/mod.rs b/server/src/amf/types/mod.rs new file mode 100644 index 0000000..af8df05 --- /dev/null +++ b/server/src/amf/types/mod.rs @@ -0,0 +1,8 @@ +pub mod amf_response; +pub use amf_response::AMFResponse; +pub mod date; +pub mod transaction_data; +pub use transaction_data::TransactionData; + +#[cfg(test)] +mod test; diff --git a/server/src/amf/types/test/mod.rs b/server/src/amf/types/test/mod.rs new file mode 100644 index 0000000..6246b0d --- /dev/null +++ b/server/src/amf/types/test/mod.rs @@ -0,0 +1,26 @@ +use chrono::NaiveDate; + +use super::date::*; + +#[test] +fn test_naive_date_from_str() { + assert_eq!( + naive_date_from_str("13 Janvier 2023").unwrap(), + NaiveDate::from_ymd_opt(2023, 1, 13).unwrap() + ); + assert_eq!( + naive_date_from_str("31 décembre 2023").unwrap(), + NaiveDate::from_ymd_opt(2023, 12, 31).unwrap() + ); + + assert!(naive_date_from_str("").is_err()); + assert!(naive_date_from_str("29 février 2023").is_err()); + assert!(naive_date_from_str("2023-01-12").is_err()); + assert!(naive_date_from_str("12 fevrier").is_err()); + assert!(naive_date_from_str("0.1 fevrier 2033").is_err()); + + assert_eq!( + naive_date_from_str("28 Fevrier 2023").unwrap(), + NaiveDate::from_ymd_opt(2023, 2, 28).unwrap() + ); +} diff --git a/server/src/amf/types/transaction_data.rs b/server/src/amf/types/transaction_data.rs new file mode 100644 index 0000000..98e20cc --- /dev/null +++ b/server/src/amf/types/transaction_data.rs @@ -0,0 +1,16 @@ +use chrono::NaiveDate; + +#[derive(Debug, Clone)] +pub struct TransactionData { + pub foreign_id: String, + pub company_name: String, + pub isin: Option, + pub person: String, + pub date_published: NaiveDate, + pub date_executed: NaiveDate, + pub exchange: String, + pub nature: String, + pub instrument: String, + pub volume: f32, + pub unit_price: f32, +} diff --git a/server/src/cors.rs b/server/src/cors.rs new file mode 100644 index 0000000..e1623e8 --- /dev/null +++ b/server/src/cors.rs @@ -0,0 +1,25 @@ +use rocket::fairing::{Fairing, Info, Kind}; +use rocket::http::Header; +use rocket::{Request, Response}; + +pub struct CORS; + +#[rocket::async_trait] +impl Fairing for CORS { + fn info(&self) -> Info { + Info { + name: "Add CORS headers to responses", + kind: Kind::Response, + } + } + + async fn on_response<'r>(&self, _request: &'r Request<'_>, response: &mut Response<'r>) { + response.set_header(Header::new("Access-Control-Allow-Origin", "*")); + response.set_header(Header::new( + "Access-Control-Allow-Methods", + "POST, GET, PATCH, OPTIONS", + )); + response.set_header(Header::new("Access-Control-Allow-Headers", "*")); + response.set_header(Header::new("Access-Control-Allow-Credentials", "true")); + } +} diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs new file mode 100644 index 0000000..2d59fd8 --- /dev/null +++ b/server/src/db/mod.rs @@ -0,0 +1,47 @@ +use std::time::Duration; + +use crate::CONFIG; +use async_trait::async_trait; +use sea_orm::{ConnectOptions, DatabaseConnection}; +use sea_orm_rocket::rocket; +use sea_orm_rocket::{rocket::figment::Figment, Database}; + +pub mod paginate; +pub mod slug; + +#[derive(Database, Debug)] +#[database("fast_insiders")] +pub struct Db(SeaOrmPool); + +#[derive(Debug, Clone)] +pub struct SeaOrmPool { + pub conn: DatabaseConnection, +} + +#[async_trait] +impl sea_orm_rocket::Pool for SeaOrmPool { + type Error = sea_orm::DbErr; + + type Connection = DatabaseConnection; + + async fn init(_figment: &Figment) -> Result { + let config = &CONFIG; + let mut options: ConnectOptions = ConnectOptions::new(config.database_url.to_owned()); + options + .max_connections(config.max_connections) + .min_connections(config.min_connections) + .connect_timeout(Duration::from_secs(config.connect_timeout)) + .acquire_timeout(Duration::from_secs(config.acquire_timeout)) + .idle_timeout(Duration::from_secs(config.idle_timeout)) + .max_lifetime(Duration::from_secs(config.max_lifetime)) + .sqlx_logging(config.sqlx_logging); + + let conn = sea_orm::Database::connect(options).await?; + + Ok(SeaOrmPool { conn }) + } + + fn borrow(&self) -> &Self::Connection { + &self.conn + } +} diff --git a/server/src/db/paginate.rs b/server/src/db/paginate.rs new file mode 100644 index 0000000..a056650 --- /dev/null +++ b/server/src/db/paginate.rs @@ -0,0 +1,102 @@ +use sea_orm::{error::DbErr, FromQueryResult}; +use sea_orm::{prelude::*, Order, QueryOrder}; +use sea_orm_rocket::Connection; +use sea_query::expr::SimpleExpr; +use serde::{Deserialize, Serialize}; + +use super::Db; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PaginatedResponse { + pub count: u64, + pub num_pages: u64, + pub list: Vec, +} + +pub async fn paginate( + conn: Connection<'_, Db>, + page: Option, + size: Option, + column: Option, + order: Option, +) -> Result, DbErr> +where + E: EntityTrait, + M: Send + Sync + FromQueryResult, + C: ColumnTrait, +{ + let db = conn.into_inner(); + let s = size.unwrap_or(20).min(50); + let selector; + if let (Some(col), Some(ord)) = (column, order) { + selector = E::find().order_by(col, ord); + } else { + selector = E::find(); + } + + let pages = selector.into_model().paginate(db, s); + let count = pages.num_items().await?; + + let num_pages = pages.num_pages().await?; + + let p = page.unwrap_or(0).min(num_pages); + + let list = pages.fetch_page(p).await?; + + let res = PaginatedResponse { + count, + num_pages, + list, + }; + + Ok(res) +} + +pub async fn paginate_also_related( + conn: Connection<'_, Db>, + page: Option, + size: Option, + column: Option, + order: Option, + filter: Option, +) -> Result)>, DbErr> +where + E: EntityTrait + Related, + R: EntityTrait, + T: Sync + Send + FromQueryResult, + K: Sync + Send + FromQueryResult, + C: ColumnTrait, +{ + let db = conn.into_inner(); + let s = size.unwrap_or(20).min(50); + + let mut selector; + if let (Some(col), Some(ord)) = (column, order) { + selector = E::find() + .find_also_related::(R::default()) + .order_by(col, ord) + } else { + selector = E::find().find_also_related::(R::default()); + } + + if let Some(fil) = filter { + selector = selector.filter(fil); + } + + let pages = selector.into_model().paginate(db, s); + let count = pages.num_items().await?; + + let num_pages = pages.num_pages().await?; + + let p = page.unwrap_or(0).min(num_pages); + + let list = pages.fetch_page(p).await?; + + let res = PaginatedResponse { + count, + num_pages, + list, + }; + + Ok(res) +} diff --git a/server/src/db/slug.rs b/server/src/db/slug.rs new file mode 100644 index 0000000..6fdd9f9 --- /dev/null +++ b/server/src/db/slug.rs @@ -0,0 +1,31 @@ +use sea_orm::{error::DbErr, ColumnTrait, ConnectionTrait, EntityTrait, QueryFilter}; +use slug::slugify; + +/// This generic function returns a slug that is not already used in the database to insert safely +pub async fn ensure_unique_slug(s: &String, column: C, db: &DB) -> Result +where + E: EntityTrait, + C: ColumnTrait, + DB: ConnectionTrait, +{ + let mut slug = slugify(s); + let mut count = 0; + // This is inefficient, we could search for all slugs that start with the new slug and take the + // last one + 1 + while E::find() + .filter(column.eq(slug.clone())) + .one(db) + .await? + .is_some() + { + count += 1; + if count == 1 { + slug += "-1"; + } else { + slug.drain(0..slug.len() - 1); + slug = format!("{}{}", slug, count); + } + } + + Ok(slug) +} diff --git a/server/src/env.rs b/server/src/env.rs new file mode 100644 index 0000000..a5c8b31 --- /dev/null +++ b/server/src/env.rs @@ -0,0 +1,85 @@ +use std::path::PathBuf; + +use serde::Deserialize; + +#[derive(Deserialize, Debug)] +pub struct Config { + pub database_url: String, + #[serde(default = "max_connections_default")] + pub max_connections: u32, + #[serde(default = "min_connections_default")] + pub min_connections: u32, + #[serde(default = "connect_timeout_default")] + pub connect_timeout: u64, + #[serde(default = "acquire_timeout_default")] + pub acquire_timeout: u64, + #[serde(default = "idle_timeout_default")] + pub idle_timeout: u64, + #[serde(default = "max_lifetime_default")] + pub max_lifetime: u64, + #[serde(default = "sqlx_logging_default")] + pub sqlx_logging: bool, + #[serde(default = "amf_informations_req")] + pub amf_informations_req: String, + #[serde(default = "amf_documents_path")] + pub amf_documents_path: String, + #[serde(default = "get_amf_transaction_interval")] + pub get_amf_transaction_interval: u64, +} + +fn max_connections_default() -> u32 { + 100 +} + +fn min_connections_default() -> u32 { + 5 +} + +fn connect_timeout_default() -> u64 { + 8 +} + +fn acquire_timeout_default() -> u64 { + 8 +} + +fn idle_timeout_default() -> u64 { + 8 +} + +fn max_lifetime_default() -> u64 { + 8 +} + +fn sqlx_logging_default() -> bool { + false +} + +fn amf_documents_path() -> String { + "https://bdif.amf-france.org/back/api/v1/documents/".to_string() +} + +fn amf_informations_req() -> String { + "https://bdif.amf-france.org/back/api/v1/informations?rechercheTexte=&typesInformation={{inf_type}}&from={{from}}&size={{size}}".to_string() +} + +fn get_amf_transaction_interval() -> u64 { + 3600 +} + +impl Config { + pub fn new() -> Self { + dotenvy::dotenv().expect("Failed to load .env file"); + let mut config = envy::from_env::().expect("Failed to load env"); + + if config.amf_documents_path.chars().last().unwrap_or('/') != '/' { + config.amf_documents_path.push('/'); + } + + config + } +} + +pub fn load_env() -> Result { + dotenvy::dotenv() +} diff --git a/server/src/lib.rs b/server/src/lib.rs new file mode 100644 index 0000000..4e72674 --- /dev/null +++ b/server/src/lib.rs @@ -0,0 +1,86 @@ +#![feature(proc_macro_hygiene, decl_macro)] + +// Macros +#[macro_use] +extern crate rocket; +#[macro_use] +extern crate lazy_static; +extern crate pretty_env_logger; +#[macro_use] +extern crate log; + +// External crates +use rocket::{Build, Rocket}; +use sea_orm_rocket::rocket::fairing::{self, AdHoc}; +use sea_orm_rocket::Database; + +// Local crates +use migration; +use migration::MigratorTrait; + +mod amf; +mod cors; +mod db; +mod env; +mod logger; +mod model; +mod repo; +mod route; +mod task; +use crate::task::run_tasks; + +// Module imports +use crate::db::Db; +use env::Config; + +lazy_static! { + /// Contains variables defind in .env file + static ref CONFIG: Config = Config::new(); +} + +async fn run_migrations(rocket: Rocket) -> fairing::Result { + let conn = &Db::fetch(&rocket).unwrap().conn; + let _ = migration::Migrator::up(conn, None).await; + Ok(rocket) +} + +async fn start_rocket() -> Result<(), sea_orm_rocket::rocket::Error> { + rocket::build() + .attach(Db::init()) + .attach(AdHoc::try_on_ignite("Migrations", run_migrations)) + .attach(crate::cors::CORS) + .mount( + "/v1", + routes![ + route::company::get_all, + route::company::get_by_isin, + route::transaction::get_by_company_id, + route::transaction::get_all, + route::in_process_transaction::get_all, + route::in_process_transaction::retry_failed_transaction, + route::in_process_transaction::retry_all + ], + ) + .launch() + .await + .map(|_| ()) +} + +#[rocket::main] +pub async fn main() -> Result<(), Box> { + env::load_env()?; + logger::init_log()?; + + // Run tasks + tokio::task::spawn(async { run_tasks().await }); + + let result = start_rocket().await; + + info!("Rocket: deorbit."); + + if let Some(err) = result.err() { + println!("Error: {}", err); + } + + Ok(()) +} diff --git a/server/src/logger/mod.rs b/server/src/logger/mod.rs new file mode 100644 index 0000000..050a88a --- /dev/null +++ b/server/src/logger/mod.rs @@ -0,0 +1,7 @@ +extern crate pretty_env_logger; +use log::SetLoggerError; + +/// For this function to do anything the RUST_LOG environment variable should be set. +pub fn init_log() -> Result<(), SetLoggerError> { + pretty_env_logger::try_init_timed() +} diff --git a/server/src/model/company.rs b/server/src/model/company.rs new file mode 100644 index 0000000..9076c18 --- /dev/null +++ b/server/src/model/company.rs @@ -0,0 +1,29 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "company")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(unique)] + pub slug: String, + #[sea_orm(unique)] + pub name: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::transaction::Entity")] + Transaction, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Transaction.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/server/src/model/in_process_transaction.rs b/server/src/model/in_process_transaction.rs new file mode 100644 index 0000000..3e2d951 --- /dev/null +++ b/server/src/model/in_process_transaction.rs @@ -0,0 +1,24 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "in_process_transaction")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub created_at: DateTime, + #[sea_orm(unique)] + pub foreign_id: String, + #[sea_orm(unique)] + pub doc_path: String, + pub failed: i8, + #[sea_orm(column_type = "Text", nullable)] + pub error_string: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/server/src/model/mod.rs b/server/src/model/mod.rs new file mode 100644 index 0000000..caf606f --- /dev/null +++ b/server/src/model/mod.rs @@ -0,0 +1,7 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6 + +pub mod prelude; + +pub mod company; +pub mod in_process_transaction; +pub mod transaction; diff --git a/server/src/model/prelude.rs b/server/src/model/prelude.rs new file mode 100644 index 0000000..559ac4b --- /dev/null +++ b/server/src/model/prelude.rs @@ -0,0 +1,5 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6 + +pub use super::company::Entity as Company; +pub use super::in_process_transaction::Entity as InProcessTransaction; +pub use super::transaction::Entity as Transaction; diff --git a/server/src/model/transaction.rs b/server/src/model/transaction.rs new file mode 100644 index 0000000..55ea84c --- /dev/null +++ b/server/src/model/transaction.rs @@ -0,0 +1,44 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.10.6 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] +#[sea_orm(table_name = "transaction")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub company_id: i32, + #[sea_orm(unique)] + pub foreign_id: String, + pub date_published: Date, + pub date_executed: Date, + #[sea_orm(column_type = "Text")] + pub person: String, + pub exchange: String, + pub nature: String, + pub isin: Option, + pub instrument: String, + pub volume: i32, + pub unit_price: f32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::company::Entity", + from = "Column::CompanyId", + to = "super::company::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Company, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Company.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/server/src/repo/company.rs b/server/src/repo/company.rs new file mode 100644 index 0000000..e3496ec --- /dev/null +++ b/server/src/repo/company.rs @@ -0,0 +1,49 @@ +use crate::db::slug::ensure_unique_slug; +use crate::model; +use sea_orm::error::DbErr; +use sea_orm::ConnectionTrait; +use sea_orm::{ActiveModelTrait, DeriveIntoActiveModel, IntoActiveModel}; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +type ActiveModel = model::company::ActiveModel; + +#[derive(Debug, PartialEq, Eq, Clone, DeriveIntoActiveModel, Serialize, Deserialize)] +pub struct NewCompany { + pub name: String, +} + +impl NewCompany { + pub fn new(name: String) -> NewCompany { + NewCompany { name } + } + + pub async fn create(&self, db: &C) -> Result + where + C: ConnectionTrait, + { + let slug = ensure_unique_slug::( + &self.name, + model::company::Column::Slug, + db, + ) + .await + .map_err(|e| CompanyRepoError::CompanyCreationErr(e))? + .into(); + + let mut comp = self.clone().into_active_model(); + comp.set(model::company::Column::Slug, slug); + + let res = comp + .insert(db) + .await + .map_err(|e| CompanyRepoError::CompanyCreationErr(e))?; + Ok(res) + } +} + +#[derive(Debug, Error)] +pub enum CompanyRepoError { + #[error("Error creating company record: {0}")] + CompanyCreationErr(DbErr), +} diff --git a/server/src/repo/in_process_transaction.rs b/server/src/repo/in_process_transaction.rs new file mode 100644 index 0000000..e59adde --- /dev/null +++ b/server/src/repo/in_process_transaction.rs @@ -0,0 +1,148 @@ +use crate::amf::service::pdf::{AMFPdf, AMFPdfError}; +use crate::amf::types::TransactionData; +use crate::amf::TransactionDataTrait; +use crate::model; +use chrono::NaiveDateTime; +use sea_orm::error::DbErr; +use sea_orm::{ + AccessMode, ActiveModelTrait, ConnectionTrait, DeriveIntoActiveModel, IntoActiveModel, + IsolationLevel, TransactionTrait, +}; +use sea_orm::DatabaseConnection; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use super::transaction::{NewTransactionFromTransactionData, TransactionRepoError}; + +type ActiveModel = model::in_process_transaction::ActiveModel; + +#[derive(Debug, PartialEq, Clone, DeriveIntoActiveModel, Serialize, Deserialize)] +pub struct NewInProcessTransaction { + pub created_at: NaiveDateTime, + pub foreign_id: String, + pub doc_path: String, + pub failed: i8, + pub error_string: Option, +} + +impl NewInProcessTransaction { + pub fn new( + foreign_id: &String, + doc_path: &String, + failed: bool, + error_string: Option, + ) -> Self { + let created_at = chrono::Utc::now().naive_utc(); + + NewInProcessTransaction { + created_at, + foreign_id: foreign_id.to_owned(), + doc_path: doc_path.to_owned(), + failed: failed.into(), + error_string, + } + } + + pub async fn create( + &self, + db: &DatabaseConnection, + ) -> Result { + let res = self + .clone() + .into_active_model() + .insert(db) + .await + .map_err(|e| InProcessTransactionError::InProcessTransactionCreationError(e))?; + + Ok(res) + } +} + +#[derive(Debug, Error)] +pub enum InProcessTransactionError { + #[error("Error creating in process transaction record: {0}")] + InProcessTransactionCreationError(DbErr), + #[error("Error creating transaction: {0}")] + TransactionCreateError(TransactionRepoError), + #[error("Database error: {0}")] + DatabaseError(DbErr), + #[error("Error during data extraction")] + DataExtractionError(AMFPdfError), + #[error("Error deleting in process transaction record")] + InProcessTransactionDeleteError(DbErr), + #[error("No document error for id {0}")] + NoDocumentError(String), + #[error("Error while extracting information from doc {0}: {1}")] + InformationExtractionError(String, AMFPdfError), +} + +#[async_trait::async_trait] +impl TransactionDataTrait for model::in_process_transaction::Model { + type Err = InProcessTransactionError; + + async fn get_transaction_data(self: &Self) -> Result { + let amf_pdf = AMFPdf::new(&self.doc_path); + let info = amf_pdf.extract_info().await.map_err(|e| { + InProcessTransactionError::InformationExtractionError(self.doc_path.to_string(), e) + })?; + + Ok(TransactionData { + foreign_id: self.foreign_id.to_owned(), + company_name: info.company_name, + isin: info.isin, + person: info.person, + date_published: info.date_published, + date_executed: info.date_executed, + exchange: info.exchange, + nature: info.nature, + instrument: info.instrument, + volume: info.volume, + unit_price: info.unit_price, + }) + } +} + +impl model::in_process_transaction::Model { + pub async fn process(&mut self, db: &C) -> Result<(), InProcessTransactionError> + where + C: ConnectionTrait + TransactionTrait, + { + match self.get_transaction_data().await { + Ok(val) => { + let txn = db + .begin_with_config( + Some(IsolationLevel::Serializable), + Some(AccessMode::ReadWrite), + ) + .await + .map_err(|e| InProcessTransactionError::DatabaseError(e))?; + + NewTransactionFromTransactionData::new_from_transaction_data(val) + .create(&txn) + .await + .map_err(|e| InProcessTransactionError::TransactionCreateError(e))?; + + self.clone() + .into_active_model() + .delete(&txn) + .await + .map_err(|e| InProcessTransactionError::DatabaseError(e))?; + + txn.commit() + .await + .map_err(|e| InProcessTransactionError::DatabaseError(e))?; + } + Err(e) => { + self.error_string = Some(e.to_string()); + self.failed = 1; + self.clone() + .into_active_model() + .update(db) + .await + .map_err(|e| InProcessTransactionError::DatabaseError(e))?; + } + }; + + Ok(()) + } +} diff --git a/server/src/repo/mod.rs b/server/src/repo/mod.rs new file mode 100644 index 0000000..d805fca --- /dev/null +++ b/server/src/repo/mod.rs @@ -0,0 +1,3 @@ +pub mod company; +pub mod in_process_transaction; +pub mod transaction; diff --git a/server/src/repo/transaction.rs b/server/src/repo/transaction.rs new file mode 100644 index 0000000..3f59f0a --- /dev/null +++ b/server/src/repo/transaction.rs @@ -0,0 +1,138 @@ +use crate::amf::types::TransactionData; +use crate::model; +use chrono::NaiveDate; +use sea_orm::error::DbErr; +use sea_orm::ConnectionTrait; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, DeriveIntoActiveModel, EntityTrait, IntoActiveModel, QueryFilter, +}; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use super::company::{CompanyRepoError, NewCompany}; + +type ActiveModel = model::transaction::ActiveModel; + +#[derive(Debug, PartialEq, Clone, DeriveIntoActiveModel, Serialize, Deserialize)] +struct NewTransaction { + pub company_id: i32, + pub foreign_id: String, + pub date_published: NaiveDate, + pub date_executed: NaiveDate, + pub person: String, + pub exchange: String, + pub nature: String, + pub isin: Option, + pub instrument: String, + pub volume: i32, + pub unit_price: f32, +} + +pub struct NewTransactionFromTransactionData { + pub company_name: String, + pub date_published: NaiveDate, + pub date_executed: NaiveDate, + pub person: String, + pub exchange: String, + pub nature: String, + pub isin: Option, + pub instrument: String, + pub volume: i32, + pub unit_price: f32, + pub foreign_id: String, +} + +impl NewTransactionFromTransactionData { + pub fn new_from_transaction_data(data: TransactionData) -> Self { + NewTransactionFromTransactionData { + foreign_id: data.foreign_id, + company_name: data.company_name, + date_published: data.date_published, + date_executed: data.date_executed, + person: data.person, + exchange: data.exchange, + nature: data.nature, + isin: data.isin, + instrument: data.instrument, + volume: data.volume as i32, + unit_price: data.unit_price, + } + } + + pub async fn create( + &self, + db: &C, + ) -> Result<(model::transaction::Model, Option), TransactionRepoError> + where + C: ConnectionTrait, + { + let comp; + if let Some(c) = model::company::Entity::find() + .filter(model::company::Column::Name.eq(self.company_name.to_owned())) + .one(db) + .await + .map_err(|e| TransactionRepoError::DatabaseError(e))? + { + comp = c; + } else { + let name = self.company_name.to_owned(); + info!("Company {} will be created", name); + let new_comp = NewCompany::new(name); + comp = new_comp + .create(db) + .await + .map_err(|e| TransactionRepoError::CompanyCreationError(e))?; + } + + let new_tr = NewTransaction { + company_id: comp.id, + foreign_id: self.foreign_id.to_owned(), + date_published: self.date_published, + date_executed: self.date_executed, + person: self.person.to_owned(), + exchange: self.exchange.to_owned(), + nature: self.nature.to_owned(), + isin: self.isin.to_owned(), + instrument: self.instrument.to_owned(), + volume: self.volume as i32, + unit_price: self.unit_price, + }; + let res = new_tr.create(db).await?; + let ret = model::transaction::Entity::find_by_id(res.id) + .find_also_related(model::company::Entity) + .one(db) + .await + .map_err(|e| TransactionRepoError::DatabaseError(e))? + .ok_or(TransactionRepoError::CreatedTransactionNotFound)?; + + Ok(ret) + } +} + +impl NewTransaction { + async fn create(&self, db: &C) -> Result + where + C: ConnectionTrait, + { + let res = self + .clone() + .into_active_model() + .insert(db) + .await + .map_err(|e| TransactionRepoError::TransactionCreationError(e))?; + + Ok(res) + } +} + +#[derive(Debug, Error)] +pub enum TransactionRepoError { + #[error("Error creating transaction record: {0}")] + TransactionCreationError(DbErr), + #[error("Error creating company record: {0}")] + CompanyCreationError(CompanyRepoError), + #[error("Error finding company record: {0}")] + DatabaseError(DbErr), + #[error("The created transaction has not been found")] + CreatedTransactionNotFound, +} diff --git a/server/src/route/company.rs b/server/src/route/company.rs new file mode 100644 index 0000000..046f8e6 --- /dev/null +++ b/server/src/route/company.rs @@ -0,0 +1,56 @@ +use rocket::{http::Status, response::status::Custom}; +use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; +use sea_orm_rocket::rocket::serde::json::Json; +use sea_orm_rocket::Connection; +use serde::{Deserialize, Serialize}; + +use crate::db::paginate::{paginate, PaginatedResponse}; +use crate::db::Db; +use crate::model::{self, company}; + +#[get("/company?&")] +pub async fn get_all( + conn: Connection<'_, Db>, + page: Option, + size: Option, +) -> Result>, Custom> { + let res = + paginate::(conn, page, size, None, None) + .await + .map_err(|e| { + Custom( + Status::InternalServerError, + format!("Database error: {}", e), + ) + })?; + + Ok(Json(res)) +} + +#[get("/company/")] +pub async fn get_by_isin( + conn: Connection<'_, Db>, + name: String, +) -> Result>, Custom> { + let db = conn.into_inner(); + let res = company::Entity::find() + .filter(company::Column::Name.contains(&name)) + .all(db) + .await + .map_err(|e| { + Custom( + Status::InternalServerError, + format!("Database error: {}", e), + ) + })?; + + Ok(Json(res)) +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct CompanyTransaction { + id: i32, + name: String, + isin: String, + transactions: Vec, +} diff --git a/server/src/route/in_process_transaction.rs b/server/src/route/in_process_transaction.rs new file mode 100644 index 0000000..8ca07d2 --- /dev/null +++ b/server/src/route/in_process_transaction.rs @@ -0,0 +1,125 @@ +use rocket::http::Status; +use rocket::response::status::Custom; +use sea_orm::{ColumnTrait, EntityTrait, Order, QueryFilter, TransactionTrait}; +use sea_orm_rocket::rocket::serde::json::Json; +use sea_orm_rocket::Connection; + +use crate::db::paginate::{paginate, PaginatedResponse}; +use crate::db::Db; +use crate::model::transaction; +use crate::model::{company, in_process_transaction}; + +#[get("/in_process_transaction?&")] +pub async fn get_all( + conn: Connection<'_, Db>, + page: Option, + size: Option, +) -> Result>, Custom> { + let res = paginate::< + in_process_transaction::Entity, + in_process_transaction::Model, + in_process_transaction::Column, + >( + conn, + page, + size, + Some(in_process_transaction::Column::CreatedAt), + Some(Order::Asc), + ) + .await + .map_err(|e| { + Custom( + Status::InternalServerError, + format!("Database error: {}", e), + ) + })?; + + Ok(Json(res)) +} + +#[get("/in_process_transaction//retry")] +pub async fn retry_failed_transaction( + conn: Connection<'_, Db>, + foreign_id: String, +) -> Result)>, Custom> { + let db = conn.into_inner(); + let txn = db.begin().await.map_err(|e| { + Custom( + Status::InternalServerError, + format!("Database error: {}", e), + ) + })?; + + let mut tr = in_process_transaction::Entity::find() + .filter(in_process_transaction::Column::Failed.eq(1)) + .filter(in_process_transaction::Column::ForeignId.eq(foreign_id.to_owned())) + .one(&txn) + .await + .map_err(|e| { + Custom( + Status::InternalServerError, + format!("Database error: {}", e), + ) + })? + .ok_or(Custom( + Status::NotFound, + format!("Failed transaction {} doesn't exist", foreign_id), + ))?; + + tr.process(&txn).await.map_err(|e| { + Custom( + Status::InternalServerError, + format!("Error retrying failed transaction {}", e), + ) + })?; + + let res = transaction::Entity::find() + .filter(transaction::Column::ForeignId.eq(foreign_id.to_owned())) + .find_also_related(company::Entity) + .one(&txn) + .await + .map_err(|e| { + Custom( + Status::InternalServerError, + format!("Database error: {}", e), + ) + })? + .ok_or(Custom( + Status::NotFound, + format!("Failed to fetch just created transaction"), + ))?; + + txn.commit().await.map_err(|e| { + Custom( + Status::InternalServerError, + format!("Database error: {}", e), + ) + })?; + + Ok(Json(res)) +} + +#[get("/in_process_transaction/retry_all")] +pub async fn retry_all(conn: Connection<'_, Db>) -> Result<(), Custom> { + let db = conn.into_inner(); + let list = in_process_transaction::Entity::find() + .all(db) + .await + .map_err(|e| { + Custom( + Status::InternalServerError, + format!("Database error: {}", e), + ) + })?; + + let mut res_list = vec![]; + for mut tr in list { + let res = tr.process(db).await; + match res { + Ok(val) => res_list.push(val), + Err(_) => (), + } + } + + Ok(()) +} diff --git a/server/src/route/mod.rs b/server/src/route/mod.rs new file mode 100644 index 0000000..d805fca --- /dev/null +++ b/server/src/route/mod.rs @@ -0,0 +1,3 @@ +pub mod company; +pub mod in_process_transaction; +pub mod transaction; diff --git a/server/src/route/transaction.rs b/server/src/route/transaction.rs new file mode 100644 index 0000000..6863229 --- /dev/null +++ b/server/src/route/transaction.rs @@ -0,0 +1,140 @@ +use chrono::NaiveDate; +use rocket::http::Status; +use rocket::response::status::Custom; +use sea_orm::{ColumnTrait, Order}; +use sea_orm_rocket::rocket::serde::json::Json; +use sea_orm_rocket::Connection; +use serde::{Deserialize, Serialize}; + +use crate::db::paginate::{paginate_also_related, PaginatedResponse}; +use crate::{db::Db, model}; + +#[get("/transaction?&")] +pub async fn get_all( + conn: Connection<'_, Db>, + page: Option, + size: Option, +) -> Result>, Custom> { + let res = paginate_also_related::< + model::transaction::Entity, + model::company::Entity, + model::transaction::Model, + model::company::Model, + model::transaction::Column, + >( + conn, + page, + size, + Some(model::transaction::Column::DatePublished), + Some(Order::Desc), + None, + ) + .await + .map_err(|e| { + Custom( + Status::InternalServerError, + format!("Database error: {}", e), + ) + })?; + + let list = res + .list + .iter() + .map(|t| TransactionCompany { + id: t.0.id, + foreign_id: t.0.foreign_id.to_owned(), + date_published: t.0.date_published, + date_executed: t.0.date_executed, + person: t.0.person.to_owned(), + exchange: t.0.exchange.to_owned(), + nature: t.0.nature.to_owned(), + isin: t.0.isin.clone(), + instrument: t.0.instrument.to_owned(), + volume: t.0.volume, + unit_price: t.0.unit_price, + company: t.1.to_owned(), + }) + .collect(); + + let res = PaginatedResponse { + count: res.count, + num_pages: res.num_pages, + list, + }; + + Ok(Json(res)) +} + +#[get("/transaction/?&")] +pub async fn get_by_company_id( + conn: Connection<'_, Db>, + company_slug: String, + page: Option, + size: Option, +) -> Result>, Custom> { + let filter = model::company::Column::Slug.eq(company_slug); + let res = paginate_also_related::< + model::transaction::Entity, + model::company::Entity, + model::transaction::Model, + model::company::Model, + model::transaction::Column, + >( + conn, + page, + size, + Some(model::transaction::Column::DatePublished), + Some(Order::Desc), + Some(filter), + ) + .await + .map_err(|e| { + Custom( + Status::InternalServerError, + format!("Database error: {}", e), + ) + })?; + + let list = res + .list + .iter() + .map(|t| TransactionCompany { + id: t.0.id, + foreign_id: t.0.foreign_id.to_owned(), + date_published: t.0.date_published, + date_executed: t.0.date_executed, + person: t.0.person.to_owned(), + exchange: t.0.exchange.to_owned(), + nature: t.0.nature.to_owned(), + isin: t.0.isin.clone(), + instrument: t.0.instrument.to_owned(), + volume: t.0.volume, + unit_price: t.0.unit_price, + company: t.1.to_owned(), + }) + .collect(); + + let res = PaginatedResponse { + count: res.count, + num_pages: res.num_pages, + list, + }; + + Ok(Json(res)) +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct TransactionCompany { + pub id: i32, + pub foreign_id: String, + pub date_published: NaiveDate, + pub date_executed: NaiveDate, + pub person: String, + pub exchange: String, + pub nature: String, + pub isin: Option, + pub instrument: String, + pub volume: i32, + pub unit_price: f32, + pub company: Option, +} diff --git a/server/src/task/get_amf_transactions.rs b/server/src/task/get_amf_transactions.rs new file mode 100644 index 0000000..2b78df4 --- /dev/null +++ b/server/src/task/get_amf_transactions.rs @@ -0,0 +1,138 @@ +use futures::StreamExt; +use sea_orm::{ + ColumnTrait, DatabaseConnection, DbErr, EntityTrait, IntoActiveModel, PaginatorTrait, + QueryFilter, +}; +use thiserror::Error; + +use crate::{ + amf::service::{ + information_req::{AMFRequest, AMFRequestType}, + pdf::AMFPdfError, + }, + model::{in_process_transaction, transaction}, + repo::in_process_transaction::{InProcessTransactionError, NewInProcessTransaction}, +}; + +pub struct GetAMFTransactions { + max_req_size: u32, +} + +#[derive(Debug, Error)] +pub enum GetAMFTransactionsError { + #[error("The transaction {0} contains no pdf document")] + NoDocumentError(String), + #[error("Database error: {0}")] + DatabaseError(DbErr), + #[error("Error extracting information from pdf at {0} : {1}")] + InformationExtractionError(String, AMFPdfError), +} + +impl Default for GetAMFTransactions { + fn default() -> Self { + GetAMFTransactions { max_req_size: 100 } + } +} + +impl GetAMFTransactions { + pub fn new(max_req_size: u32) -> Self { + GetAMFTransactions { max_req_size } + } + + /// This task will extract the information from all AMF transactions until one is already found + /// in the database. Another function should be used to download individual records. + pub async fn run(&self, db: &DatabaseConnection) -> Result<(), GetAMFTransactionsError> { + info!("Starting AMF transaction download task"); + let mut from = 0; + + let mut req = AMFRequest::new(AMFRequestType::DD, from, self.max_req_size); + let mut tr_to_process = Vec::new(); + 'outer: while let Some(resp) = req.get_list().await.ok() { + info!( + "Downloading hit list from {} to {}", + from, + self.max_req_size + from + ); + + let list = resp.get_hits(); + + for hit in list.iter() { + let number = &hit.source.numero; + + if transaction::Entity::find() + .filter(transaction::Column::ForeignId.eq(number.to_owned())) + .one(db) + .await + .map_err(|e| GetAMFTransactionsError::DatabaseError(e))? + .is_some() + { + // We've saved this transaction before, so we stop here. + break 'outer; + } + + if in_process_transaction::Entity::find() + .filter(in_process_transaction::Column::ForeignId.eq(number.to_owned())) + .one(db) + .await + .map_err(|e| GetAMFTransactionsError::DatabaseError(e))? + .is_some() + { + // We've registered this transaction before, so we stop here. + break 'outer; + } + + tr_to_process.push( + NewInProcessTransaction::new( + &hit.get_foreign_id(), + &hit.get_documents()[0].path, + false, + None, + ) + .into_active_model(), + ); + } + from += self.max_req_size; + req = AMFRequest::new(AMFRequestType::DD, from, self.max_req_size); + } + + if !tr_to_process.is_empty() { + in_process_transaction::Entity::insert_many(tr_to_process) + .exec(db) + .await + .map_err(|e| GetAMFTransactionsError::DatabaseError(e))?; + } + + let mut to_run = in_process_transaction::Entity::find() + .filter(in_process_transaction::Column::Failed.eq(0)) + .paginate(db, 100); + + let n_not_failed = to_run + .num_items() + .await + .map_err(|e| GetAMFTransactionsError::DatabaseError(e))?; + + if n_not_failed == 0 { + info!("No new transactions to process since last run"); + return Ok(()); + } + + info!("{} transactions will be processed", n_not_failed); + + while let Some(page) = to_run + .fetch_and_next() + .await + .map_err(|e| GetAMFTransactionsError::DatabaseError(e))? + { + let mut futures = Vec::new(); + for tr in page.iter() { + futures.push(async move { tr.clone().process(db).await }); + } + let stream = futures::stream::iter(futures).buffer_unordered(10); + let _results: Vec> = stream.collect().await; + } + + info!("AMF transactions download task finished execution"); + + Ok(()) + } +} diff --git a/server/src/task/mod.rs b/server/src/task/mod.rs new file mode 100644 index 0000000..bba3a19 --- /dev/null +++ b/server/src/task/mod.rs @@ -0,0 +1,41 @@ +use std::time::Duration; + +use sea_orm::ConnectOptions; + +use crate::{task::get_amf_transactions::GetAMFTransactions, CONFIG}; + +pub mod get_amf_transactions; + +trait TaskTrait { + type Err; + + fn init(&self) -> Result<(), Self::Err>; + + fn run(&self) -> Result<(), Self::Err>; +} + +pub async fn run_tasks() -> Result<(), sea_orm::DbErr> { + let config = &CONFIG; + info!("Creating task db pool"); + let mut options: ConnectOptions = ConnectOptions::new(config.database_url.to_owned()); + options + .max_connections(config.max_connections) + .min_connections(config.min_connections) + .connect_timeout(Duration::from_secs(config.connect_timeout)) + .acquire_timeout(Duration::from_secs(config.acquire_timeout)) + .idle_timeout(Duration::from_secs(config.idle_timeout)) + .max_lifetime(Duration::from_secs(config.max_lifetime)) + .sqlx_logging(config.sqlx_logging); + + let tasks_pool = sea_orm::Database::connect(options).await?; + + let mut inter = tokio::time::interval(Duration::from_secs(config.get_amf_transaction_interval)); + loop { + inter.tick().await; + info!("Running task: getamftransactions"); + match GetAMFTransactions::new(1000).run(&tasks_pool).await { + Ok(_) => (), + Err(e) => error!("Task failed: {}", e), + }; + } +} diff --git a/src/bin/server.rs b/src/bin/server.rs new file mode 100644 index 0000000..e877c35 --- /dev/null +++ b/src/bin/server.rs @@ -0,0 +1,6 @@ +use server; + +fn main() -> Result<(), Box> { + server::main()?; + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..5778927 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2 @@ +fn main() -> () { +}