diff --git a/.cargo/config.toml b/.cargo/config.toml index 610b7b2e..d29b0de3 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,4 +1,3 @@ [alias] ts = ["test", "--features", "testing"] # cargo ts tw = ["test", "--workspace", "--features", "testing"] # cargo tw -td = ["test", "--doc", "-p"] # cargo td diff --git a/CREDITS.md b/CREDITS.md index f61bf867..eaf97333 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -26,6 +26,13 @@ para mostrar un banner de presentación en el terminal con el nombre de la aplic * [starwars.flf](http://www.figlet.org/fontdb_example.cgi?font=starwars.flf) de *Ryan Youck* +# 🎨 CSS + +La extensión `pagetop-bootsier` es un tema que integra [Bootstrap 5.3.8](https://getbootstrap.com/) +para los estilos y componentes de la interfaz. Bootstrap está distribuido bajo licencia +[MIT](https://github.com/twbs/bootstrap/blob/main/LICENSE). + + # 👾 Icono "La Mascota" sonriente es una simpática creación de [Webalys](https://www.iconfinder.com/webalys). diff --git a/Cargo.lock b/Cargo.lock index 8b01826c..bf8d11ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.11.1", + "bitflags", "bytes", "futures-core", "futures-sink", @@ -29,7 +29,7 @@ dependencies = [ "actix-service", "actix-utils", "actix-web", - "bitflags 2.11.1", + "bitflags", "bytes", "derive_more 2.1.1", "futures-core", @@ -53,7 +53,7 @@ dependencies = [ "actix-service", "actix-utils", "base64 0.22.1", - "bitflags 2.11.1", + "bitflags", "brotli", "bytes", "bytestring", @@ -73,7 +73,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rand 0.10.1", - "sha1 0.11.0", + "sha1", "smallvec", "tokio", "tokio-util", @@ -287,12 +287,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "aliasable" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" - [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -379,196 +373,6 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener 2.5.3", - "futures-core", -] - -[[package]] -name = "async-channel" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-executor" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand 2.4.1", - "futures-lite 2.6.1", - "pin-project-lite", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" -dependencies = [ - "async-channel 2.5.0", - "async-executor", - "async-io 2.6.0", - "async-lock 3.4.2", - "blocking", - "futures-lite 2.6.1", - "once_cell", -] - -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock 2.8.0", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.28", - "slab", - "socket2 0.4.10", - "waker-fn", -] - -[[package]] -name = "async-io" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" -dependencies = [ - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite 2.6.1", - "parking", - "polling 3.11.0", - "rustix 1.1.4", - "slab", - "windows-sys 0.61.2", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", -] - -[[package]] -name = "async-lock" -version = "3.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" -dependencies = [ - "event-listener 5.4.1", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-std" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" -dependencies = [ - "async-channel 1.9.0", - "async-global-executor", - "async-io 2.6.0", - "async-lock 3.4.2", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite 2.6.1", - "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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - -[[package]] -name = "async-trait" -version = "0.1.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "atoi" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" -dependencies = [ - "num-traits", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - [[package]] name = "autocfg" version = "1.5.0" @@ -587,26 +391,11 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64ct" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" -dependencies = [ - "serde_core", -] [[package]] name = "block-buffer" @@ -626,19 +415,6 @@ dependencies = [ "hybrid-array", ] -[[package]] -name = "blocking" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" -dependencies = [ - "async-channel 2.5.0", - "async-task", - "futures-io", - "futures-lite 2.6.1", - "piper", -] - [[package]] name = "brotli" version = "8.0.2" @@ -699,9 +475,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.62" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", "jobserver", @@ -813,15 +589,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7439becb5fafc780b6f4de382b1a7a3e70234afe783854a4702ee8adbb838609" -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "config" version = "0.15.22" @@ -834,12 +601,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - [[package]] name = "const-oid" version = "0.10.2" @@ -879,16 +640,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -913,21 +664,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" - [[package]] name = "crc32fast" version = "1.5.0" @@ -965,15 +701,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -1009,51 +736,6 @@ dependencies = [ "cipher", ] -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid 0.9.6", - "pem-rfc7468", - "zeroize", -] - [[package]] name = "deranged" version = "0.5.8" @@ -1106,19 +788,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "const-oid 0.9.6", "crypto-common 0.1.7", "subtle", ] [[package]] name = "digest" -version = "0.11.3" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" dependencies = [ "block-buffer 0.12.0", - "const-oid 0.10.2", + "const-oid", "crypto-common 0.2.1", ] @@ -1133,21 +814,6 @@ dependencies = [ "syn", ] -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -dependencies = [ - "serde", -] - [[package]] name = "encoding_rs" version = "0.8.35" @@ -1173,53 +839,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "etcetera" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" -dependencies = [ - "cfg-if", - "home", - "windows-sys 0.48.0", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "event-listener" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" -dependencies = [ - "event-listener 5.4.1", - "pin-project-lite", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - [[package]] name = "fastrand" version = "2.4.1" @@ -1324,8 +943,6 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ - "futures-core", - "futures-sink", "spin", ] @@ -1341,21 +958,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[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.2.2" @@ -1365,104 +967,12 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "futures" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" -dependencies = [ - "futures-core", - "futures-sink", -] - [[package]] name = "futures-core" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" -[[package]] -name = "futures-executor" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-intrusive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" -dependencies = [ - "futures-core", - "lock_api", - "parking_lot", -] - -[[package]] -name = "futures-io" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-lite" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" -dependencies = [ - "fastrand 2.4.1", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - -[[package]] -name = "futures-macro" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "futures-sink" version = "0.3.32" @@ -1481,13 +991,8 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ - "futures-channel", "futures-core", - "futures-io", - "futures-macro", - "futures-sink", "futures-task", - "memchr", "pin-project-lite", "slab", ] @@ -1581,18 +1086,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "grass" version = "0.13.4" @@ -1653,31 +1146,14 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "allocator-api2", - "equivalent", "foldhash", ] [[package]] name = "hashbrown" -version = "0.17.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" - -[[package]] -name = "hashlink" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" -dependencies = [ - "hashbrown 0.15.5", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "heck" @@ -1685,24 +1161,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[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.4" @@ -1721,15 +1179,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "home" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "http" version = "0.2.12" @@ -1880,12 +1329,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "1.1.0" @@ -1936,7 +1379,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -1950,17 +1393,6 @@ dependencies = [ "rustversion", ] -[[package]] -name = "inherent" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c727f80bfa4a6c6e2508d2f05b6f4bfce242030bd88ed15ae5331c5b5d30fba7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "inout" version = "0.1.4" @@ -1970,15 +1402,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "intl-memoizer" version = "0.5.3" @@ -1998,17 +1421,6 @@ dependencies = [ "unic-langid", ] -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -2033,9 +1445,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.98" +version = "0.3.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" dependencies = [ "cfg-if", "futures-util", @@ -2043,15 +1455,6 @@ 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 = "language-tags" version = "0.3.2" @@ -2072,9 +1475,6 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin", -] [[package]] name = "leb128fmt" @@ -2088,41 +1488,6 @@ version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - -[[package]] -name = "libredox" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" -dependencies = [ - "bitflags 2.11.1", - "libc", - "plain", - "redox_syscall 0.7.5", -] - -[[package]] -name = "libsqlite3-sys" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -2166,9 +1531,6 @@ name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -dependencies = [ - "value-bag", -] [[package]] name = "matchers" @@ -2179,16 +1541,6 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - [[package]] name = "memchr" version = "2.8.0" @@ -2239,23 +1591,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e94e1e6445d314f972ff7395df2de295fe51b71821694f0b0e1e79c4f12c8577" -[[package]] -name = "native-tls" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -2265,48 +1600,12 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "num-bigint-dig" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" -dependencies = [ - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand 0.8.6", - "smallvec", - "zeroize", -] - [[package]] name = "num-conv" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -2314,7 +1613,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -2335,82 +1633,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "openssl" -version = "0.10.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf0b434746ee2832f4f0baf10137e1cabb18cbe6912c69e2e33263c45250f542" -dependencies = [ - "bitflags 2.11.1", - "cfg-if", - "foreign-types", - "libc", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" - -[[package]] -name = "openssl-sys" -version = "0.9.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "158fe5b292746440aa6e7a7e690e55aeb72d41505e2804c23c6973ad0e9c9781" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "ordered-float" -version = "4.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" -dependencies = [ - "num-traits", -] - -[[package]] -name = "ouroboros" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59" -dependencies = [ - "aliasable", - "ouroboros_macro", - "static_assertions", -] - -[[package]] -name = "ouroboros_macro" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn", -] - [[package]] name = "pagetop" version = "0.5.0" @@ -2489,19 +1711,6 @@ dependencies = [ "pastey", ] -[[package]] -name = "pagetop-seaorm" -version = "0.0.4" -dependencies = [ - "async-trait", - "futures", - "pagetop", - "sea-orm", - "sea-schema", - "serde", - "url", -] - [[package]] name = "pagetop-statics" version = "0.1.3" @@ -2514,12 +1723,6 @@ dependencies = [ "path-slash 0.2.1", ] -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - [[package]] name = "parking_lot" version = "0.12.5" @@ -2538,7 +1741,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.18", + "redox_syscall", "smallvec", "windows-link", ] @@ -2576,15 +1779,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - [[package]] name = "percent-encoding" version = "2.3.2" @@ -2635,18 +1829,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.12" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf0d9e68100b3a7989b4901972f265cd542e560a3a8a724e1e20322f4d06ce9" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.12" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a990e22f43e84855daf260dded30524ef4a9021cc7541c26540500a50b624389" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", @@ -2659,86 +1853,12 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" -dependencies = [ - "atomic-waker", - "fastrand 2.4.1", - "futures-io", -] - -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - [[package]] name = "pkg-config" version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] - -[[package]] -name = "polling" -version = "3.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi 0.5.2", - "pin-project-lite", - "rustix 1.1.4", - "windows-sys 0.61.2", -] - [[package]] name = "polyval" version = "0.6.2" @@ -2785,28 +1905,6 @@ dependencies = [ "syn", ] -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -2832,7 +1930,6 @@ dependencies = [ "quote", "syn", "version_check", - "yansi", ] [[package]] @@ -2938,16 +2035,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.1", -] - -[[package]] -name = "redox_syscall" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" -dependencies = [ - "bitflags 2.11.1", + "bitflags", ] [[package]] @@ -2985,26 +2073,6 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" -[[package]] -name = "rsa" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" -dependencies = [ - "const-oid 0.9.6", - "digest 0.10.7", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core 0.6.4", - "signature", - "spki", - "subtle", - "zeroize", -] - [[package]] name = "rustc-hash" version = "2.1.2" @@ -3020,30 +2088,16 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.37.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - [[package]] name = "rustix" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.1", + "bitflags", "errno", "libc", - "linux-raw-sys 0.12.1", + "linux-raw-sys", "windows-sys 0.61.2", ] @@ -3068,152 +2122,12 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "schannel" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sea-bae" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f694a6ab48f14bc063cfadff30ab551d3c7e46d8f81836c51989d548f44a2a25" -dependencies = [ - "heck 0.4.1", - "proc-macro-error2", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sea-orm" -version = "1.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc312fedd460a47ea563911761d254a84e7b51d8cc73ec92c929e78f33fa957" -dependencies = [ - "async-stream", - "async-trait", - "derive_more 2.1.1", - "futures-util", - "log", - "ouroboros", - "sea-orm-macros", - "sea-query", - "sea-query-binder", - "serde", - "sqlx", - "strum", - "thiserror", - "tracing", - "url", -] - -[[package]] -name = "sea-orm-macros" -version = "1.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9a3f90e336ec74803e8eb98c61bc98754c1adfba3b4f84d946237b752b1c88" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "sea-bae", - "syn", - "unicode-ident", -] - -[[package]] -name = "sea-query" -version = "0.32.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5d1c518eaf5eda38e5773f902b26ab6d5e9e9e2bb2349ca6c64cf96f80448c" -dependencies = [ - "inherent", - "ordered-float", - "sea-query-derive", -] - -[[package]] -name = "sea-query-binder" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0019f47430f7995af63deda77e238c17323359af241233ec768aba1faea7608" -dependencies = [ - "sea-query", - "sqlx", -] - -[[package]] -name = "sea-query-derive" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae0cbad6ab996955664982739354128c58d16e126114fe88c2a493642502aab" -dependencies = [ - "darling", - "heck 0.4.1", - "proc-macro2", - "quote", - "syn", - "thiserror", -] - -[[package]] -name = "sea-schema" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2239ff574c04858ca77485f112afea1a15e53135d3097d0c86509cef1def1338" -dependencies = [ - "futures", - "sea-query", - "sea-schema-derive", -] - -[[package]] -name = "sea-schema-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "debdc8729c37fdbf88472f97fd470393089f997a909e535ff67c544d18cfccf0" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "security-framework" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" -dependencies = [ - "bitflags 2.11.1", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "self_cell" version = "1.2.2" @@ -3290,17 +2204,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] - [[package]] name = "sha1" version = "0.11.0" @@ -3309,7 +2212,7 @@ checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "digest 0.11.3", + "digest 0.11.2", ] [[package]] @@ -3348,16 +2251,6 @@ dependencies = [ "libc", ] -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - [[package]] name = "simd-adler32" version = "0.3.9" @@ -3366,9 +2259,9 @@ checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "siphasher" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" @@ -3381,19 +2274,6 @@ name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -dependencies = [ - "serde", -] - -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] [[package]] name = "socket2" @@ -3424,240 +2304,18 @@ dependencies = [ "lock_api", ] -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "sqlx" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" -dependencies = [ - "sqlx-core", - "sqlx-macros", - "sqlx-mysql", - "sqlx-postgres", - "sqlx-sqlite", -] - -[[package]] -name = "sqlx-core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" -dependencies = [ - "async-io 1.13.0", - "async-std", - "base64 0.22.1", - "bytes", - "crc", - "crossbeam-queue", - "either", - "event-listener 5.4.1", - "futures-core", - "futures-intrusive", - "futures-io", - "futures-util", - "hashbrown 0.15.5", - "hashlink", - "indexmap", - "log", - "memchr", - "native-tls", - "once_cell", - "percent-encoding", - "serde", - "serde_json", - "sha2", - "smallvec", - "thiserror", - "tracing", - "url", -] - -[[package]] -name = "sqlx-macros" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" -dependencies = [ - "proc-macro2", - "quote", - "sqlx-core", - "sqlx-macros-core", - "syn", -] - -[[package]] -name = "sqlx-macros-core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" -dependencies = [ - "async-std", - "dotenvy", - "either", - "heck 0.5.0", - "hex", - "once_cell", - "proc-macro2", - "quote", - "serde", - "serde_json", - "sha2", - "sqlx-core", - "sqlx-mysql", - "sqlx-postgres", - "sqlx-sqlite", - "syn", - "url", -] - -[[package]] -name = "sqlx-mysql" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" -dependencies = [ - "atoi", - "base64 0.22.1", - "bitflags 2.11.1", - "byteorder", - "bytes", - "crc", - "digest 0.10.7", - "dotenvy", - "either", - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "generic-array", - "hex", - "hkdf", - "hmac", - "itoa", - "log", - "md-5", - "memchr", - "once_cell", - "percent-encoding", - "rand 0.8.6", - "rsa", - "serde", - "sha1 0.10.6", - "sha2", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror", - "tracing", - "whoami", -] - -[[package]] -name = "sqlx-postgres" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" -dependencies = [ - "atoi", - "base64 0.22.1", - "bitflags 2.11.1", - "byteorder", - "crc", - "dotenvy", - "etcetera", - "futures-channel", - "futures-core", - "futures-util", - "hex", - "hkdf", - "hmac", - "home", - "itoa", - "log", - "md-5", - "memchr", - "once_cell", - "rand 0.8.6", - "serde", - "serde_json", - "sha2", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror", - "tracing", - "whoami", -] - -[[package]] -name = "sqlx-sqlite" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" -dependencies = [ - "atoi", - "flume", - "futures-channel", - "futures-core", - "futures-executor", - "futures-intrusive", - "futures-util", - "libsqlite3-sys", - "log", - "percent-encoding", - "serde", - "serde_urlencoded", - "sqlx-core", - "thiserror", - "tracing", - "url", -] - [[package]] name = "stable_deref_trait" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "stringprep" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" -dependencies = [ - "unicode-bidi", - "unicode-normalization", - "unicode-properties", -] - [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" - [[package]] name = "substring" version = "1.4.5" @@ -3707,10 +2365,10 @@ version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ - "fastrand 2.4.1", + "fastrand", "getrandom 0.4.2", "once_cell", - "rustix 1.1.4", + "rustix", "windows-sys 0.61.2", ] @@ -3720,7 +2378,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ - "rustix 1.1.4", + "rustix", "windows-sys 0.61.2", ] @@ -3795,26 +2453,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "tinyvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.52.3" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -4035,33 +2678,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" -[[package]] -name = "unicode-bidi" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" - [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" -[[package]] -name = "unicode-normalization" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-properties" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" - [[package]] name = "unicode-segmentation" version = "1.13.2" @@ -4131,30 +2753,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "value-bag" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" - -[[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.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" - [[package]] name = "walkdir" version = "2.5.0" @@ -4189,17 +2793,11 @@ dependencies = [ "wit-bindgen 0.51.0", ] -[[package]] -name = "wasite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" - [[package]] name = "wasm-bindgen" -version = "0.2.121" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" dependencies = [ "cfg-if", "once_cell", @@ -4208,21 +2806,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.121" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4230,9 +2818,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.121" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" dependencies = [ "bumpalo", "proc-macro2", @@ -4243,9 +2831,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.121" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" dependencies = [ "unicode-ident", ] @@ -4278,38 +2866,12 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.11.1", + "bitflags", "hashbrown 0.15.5", "indexmap", "semver", ] -[[package]] -name = "whoami" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" -dependencies = [ - "libredox", - "wasite", -] - -[[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.11" @@ -4319,12 +2881,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[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-core" version = "0.62.2" @@ -4384,22 +2940,13 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -4411,67 +2958,34 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -4484,48 +2998,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -4563,7 +3053,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "wit-parser", ] @@ -4574,7 +3064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "indexmap", "prettyplease", "syn", @@ -4605,7 +3095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.11.1", + "bitflags", "indexmap", "log", "serde", @@ -4641,12 +3131,6 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" -[[package]] -name = "yansi" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" - [[package]] name = "yoke" version = "0.8.2" @@ -4711,12 +3195,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" - [[package]] name = "zerotrie" version = "0.2.4" diff --git a/Cargo.toml b/Cargo.toml index 48bc600c..d809c122 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,7 +69,6 @@ members = [ # Extensions "extensions/pagetop-aliner", "extensions/pagetop-bootsier", - "extensions/pagetop-seaorm", ] [workspace.package] @@ -89,6 +88,5 @@ pagetop-statics = { version = "0.1", path = "helpers/pagetop-statics" } # Extensions pagetop-aliner = { version = "0.1", path = "extensions/pagetop-aliner" } pagetop-bootsier = { version = "0.1", path = "extensions/pagetop-bootsier" } -pagetop-seaorm = { version = "0.0", path = "extensions/pagetop-seaorm" } # PageTop pagetop = { version = "0.5", path = "." } diff --git a/README.md b/README.md index 604c4b3c..463855f2 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,8 @@ [![Descargas](https://img.shields.io/crates/d/pagetop.svg?label=Descargas&style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop) [![Licencia](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?label=Licencia&style=for-the-badge)](https://git.cillero.es/manuelcillero/pagetop#licencia) - -
+ PageTop reivindica la esencia de la web clásica usando [Rust](https://www.rust-lang.org/es) para la creación de soluciones web SSR (*renderizadas en el servidor*) basadas en HTML, CSS y JavaScript. @@ -110,29 +109,22 @@ El código se organiza en un *workspace* donde actualmente se incluyen los sigui tema basado en [Bootstrap](https://getbootstrap.com) para integrar su catálogo de estilos y componentes flexibles. - * **[pagetop-seaorm](https://git.cillero.es/manuelcillero/pagetop/src/branch/main/extensions/pagetop-seaorm)**, - integra [SeaORM](https://www.sea-ql.org/SeaORM) para acceder a bases de datos relacionales. - ## 🧪 Pruebas Para simplificar el flujo de trabajo, el repositorio incluye varios **alias de Cargo** declarados en `.cargo/config.toml`. Basta con ejecutarlos desde la raíz del proyecto: -| Comando | Descripción | -| ----------------------- | --------------------------------------------------------------- | -| `cargo ts` | Lanza **todos los tests** de `pagetop` | -| `cargo ts --test util` | Lanza los tests de integración del archivo `tests/util.rs` | -| `cargo ts --doc locale` | Lanza los *doctests* de `pagetop` cuyo *path* contiene `locale` | -| `cargo tw` | Lanza **todos los tests** del *workspace* | -| `cargo td ` | Lanza los *doctests* de un *crate* concreto del *workspace* | +| Comando | Descripción | +| ------- | ----------- | +| `cargo ts` | Ejecuta los tests de `pagetop` (*unit + integration*) con la *feature* `testing`. | +| `cargo ts --test util` | Lanza sólo las pruebas de integración del módulo `util`. | +| `cargo ts --doc locale` | Lanza las pruebas de la documentación del módulo `locale`. | +| `cargo tw` | Ejecuta los tests de **todos los paquetes** del *workspace*. | > **Nota** -> * Todos los alias, excepto `cargo td`, aplican la *feature* `testing` para los *crates* que la -> declaren. -> * Cuando lanza **todos los tests** se incluyen las pruebas unitarias, de integración y *doctests*. -> * Los alias suprimen las trazas del registro de eventos. Para activarlas usa directamente -> `cargo test`. +> Estos alias ya compilan con la configuración adecuada. No requieren `--no-default-features`. +> Si quieres **activar** las trazas del registro de eventos entonces usa simplemente `cargo test`. ## 🚧 Advertencia diff --git a/examples/form-controls.rs b/examples/form-controls.rs index 4a6fc6c0..e49844e8 100644 --- a/examples/form-controls.rs +++ b/examples/form-controls.rs @@ -1,6 +1,6 @@ use pagetop::prelude::*; -use pagetop_bootsier::theme::*; +use pagetop_bootsier::prelude::*; include_locales!(LOC from "examples/locale"); diff --git a/examples/navbar-menus.rs b/examples/navbar-menus.rs index 38918aed..a0d85f3b 100644 --- a/examples/navbar-menus.rs +++ b/examples/navbar-menus.rs @@ -1,6 +1,6 @@ use pagetop::prelude::*; -use pagetop_bootsier::theme::*; +use pagetop_bootsier::prelude::*; include_locales!(LOC from "examples/locale"); diff --git a/extensions/pagetop-aliner/README.md b/extensions/pagetop-aliner/README.md index 7b772591..09a337eb 100644 --- a/extensions/pagetop-aliner/README.md +++ b/extensions/pagetop-aliner/README.md @@ -9,6 +9,7 @@ [![Descargas](https://img.shields.io/crates/d/pagetop-aliner.svg?label=Descargas&style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-aliner) [![Licencia](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?label=Licencia&style=for-the-badge)](https://git.cillero.es/manuelcillero/pagetop/src/branch/main/extensions/pagetop-aliner#licencia) +
## 🧭 Sobre PageTop diff --git a/extensions/pagetop-aliner/src/lib.rs b/extensions/pagetop-aliner/src/lib.rs index e88a9142..95f22196 100644 --- a/extensions/pagetop-aliner/src/lib.rs +++ b/extensions/pagetop-aliner/src/lib.rs @@ -83,12 +83,9 @@ async fn homepage(request: HttpRequest) -> ResultPage { use pagetop::prelude::*; -include_locales!(LOCALES_ALINER); - -/// Implementa el tema. +/// Implementa el tema para usar en pruebas que muestran el esquema de páginas HTML. /// -/// Define un tema mínimo que muestra esquemáticamente la composición de las páginas HTML; útil -/// para: +/// Define un tema mínimo útil para: /// /// - Comprobar el funcionamiento de temas, plantillas y regiones. /// - Verificar integración de componentes y composiciones (*layouts*) sin estilos complejos. @@ -97,14 +94,6 @@ include_locales!(LOCALES_ALINER); pub struct Aliner; impl Extension for Aliner { - fn name(&self) -> L10n { - L10n::t("extension_name", &LOCALES_ALINER) - } - - fn description(&self) -> L10n { - L10n::t("extension_description", &LOCALES_ALINER) - } - fn theme(&self) -> Option { Some(&Self) } diff --git a/extensions/pagetop-aliner/src/locale/en-US/extension.ftl b/extensions/pagetop-aliner/src/locale/en-US/extension.ftl deleted file mode 100644 index e4fca26d..00000000 --- a/extensions/pagetop-aliner/src/locale/en-US/extension.ftl +++ /dev/null @@ -1,2 +0,0 @@ -extension_name = Aliner -extension_description = Minimal theme that schematically shows the HTML page composition. diff --git a/extensions/pagetop-aliner/src/locale/es-ES/extension.ftl b/extensions/pagetop-aliner/src/locale/es-ES/extension.ftl deleted file mode 100644 index 5501e15a..00000000 --- a/extensions/pagetop-aliner/src/locale/es-ES/extension.ftl +++ /dev/null @@ -1,2 +0,0 @@ -extension_name = Aliner -extension_description = Tema mínimo que muestra esquemáticamente la composición de las páginas HTML. \ No newline at end of file diff --git a/extensions/pagetop-bootsier/README.md b/extensions/pagetop-bootsier/README.md index edb0be75..b34eeb51 100644 --- a/extensions/pagetop-bootsier/README.md +++ b/extensions/pagetop-bootsier/README.md @@ -9,6 +9,7 @@ [![Descargas](https://img.shields.io/crates/d/pagetop-bootsier.svg?label=Descargas&style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-bootsier) [![Licencia](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?label=Licencia&style=for-the-badge)](https://git.cillero.es/manuelcillero/pagetop/src/branch/main/extensions/pagetop-bootsier#licencia) +
## 🧭 Sobre PageTop @@ -79,13 +80,6 @@ async fn homepage(request: HttpRequest) -> ResultPage { ``` -## 📚 Créditos - -Este *crate* integra la biblioteca de estilos [Bootstrap 5.3.8](https://getbootstrap.com/) para -definir el comportamiento, la apariencia y los componentes de la interfaz. Bootstrap se distribuye -bajo licencia [MIT](https://github.com/twbs/bootstrap/blob/main/LICENSE). - - ## 🚧 Advertencia **PageTop** es un proyecto personal para aprender [Rust](https://www.rust-lang.org/es) y conocer su diff --git a/extensions/pagetop-bootsier/src/lib.rs b/extensions/pagetop-bootsier/src/lib.rs index ca2a80c8..d562ec09 100644 --- a/extensions/pagetop-bootsier/src/lib.rs +++ b/extensions/pagetop-bootsier/src/lib.rs @@ -96,6 +96,12 @@ pub mod config; pub mod theme; +/// *Prelude* del tema. +pub mod prelude { + pub use crate::config::*; + pub use crate::theme::*; +} + /// Plantillas que Bootsier añade. #[derive(AutoDefault)] pub enum BootsierTemplate { @@ -128,14 +134,6 @@ impl Template for BootsierTemplate { pub struct Bootsier; impl Extension for Bootsier { - fn name(&self) -> L10n { - L10n::t("extension_name", &LOCALES_BOOTSIER) - } - - fn description(&self) -> L10n { - L10n::t("extension_description", &LOCALES_BOOTSIER) - } - fn theme(&self) -> Option { Some(&Self) } diff --git a/extensions/pagetop-bootsier/src/locale/en-US/extension.ftl b/extensions/pagetop-bootsier/src/locale/en-US/extension.ftl deleted file mode 100644 index b2820621..00000000 --- a/extensions/pagetop-bootsier/src/locale/en-US/extension.ftl +++ /dev/null @@ -1,2 +0,0 @@ -extension_name = Bootsier -extension_description = Bootstrap-based theme with flexible styles and components. diff --git a/extensions/pagetop-bootsier/src/locale/es-ES/extension.ftl b/extensions/pagetop-bootsier/src/locale/es-ES/extension.ftl deleted file mode 100644 index 7323cc1b..00000000 --- a/extensions/pagetop-bootsier/src/locale/es-ES/extension.ftl +++ /dev/null @@ -1,2 +0,0 @@ -extension_name = Bootsier -extension_description = Tema basado en Bootstrap para aplicar su catálogo de estilos y componentes flexibles. diff --git a/extensions/pagetop-bootsier/src/theme/attrs/border.rs b/extensions/pagetop-bootsier/src/theme/attrs/border.rs index af66db78..b46a5c6b 100644 --- a/extensions/pagetop-bootsier/src/theme/attrs/border.rs +++ b/extensions/pagetop-bootsier/src/theme/attrs/border.rs @@ -58,7 +58,7 @@ impl BorderColor { /// # Ejemplos /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// assert_eq!(BorderColor::Theme(Color::Primary).to_class(), "border-primary"); /// assert_eq!(BorderColor::Subtle(Color::Warning).to_class(), "border-warning-subtle"); /// assert_eq!(BorderColor::Black.to_class(), "border-black"); diff --git a/extensions/pagetop-bootsier/src/theme/attrs/breakpoint.rs b/extensions/pagetop-bootsier/src/theme/attrs/breakpoint.rs index ec2c8568..992f8525 100644 --- a/extensions/pagetop-bootsier/src/theme/attrs/breakpoint.rs +++ b/extensions/pagetop-bootsier/src/theme/attrs/breakpoint.rs @@ -70,7 +70,7 @@ impl BreakPoint { /// # Ejemplos /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// let bp = BreakPoint::MD; /// assert_eq!(bp.class_with("col", ""), "col-md"); /// assert_eq!(bp.class_with("col", "6"), "col-md-6"); diff --git a/extensions/pagetop-bootsier/src/theme/attrs/button.rs b/extensions/pagetop-bootsier/src/theme/attrs/button.rs index 01e0dd57..dc74fbea 100644 --- a/extensions/pagetop-bootsier/src/theme/attrs/button.rs +++ b/extensions/pagetop-bootsier/src/theme/attrs/button.rs @@ -76,7 +76,7 @@ impl ButtonColor { /// # Ejemplos /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// assert_eq!( /// ButtonColor::Background(Color::Primary).to_class(), /// "btn-primary" @@ -132,7 +132,7 @@ impl ButtonSize { /// # Ejemplos /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// assert_eq!(ButtonSize::Small.to_class(), "btn-sm"); /// assert_eq!(ButtonSize::Large.to_class(), "btn-lg"); /// assert_eq!(ButtonSize::Default.to_class(), ""); diff --git a/extensions/pagetop-bootsier/src/theme/attrs/color.rs b/extensions/pagetop-bootsier/src/theme/attrs/color.rs index eb9f57d4..c408aadc 100644 --- a/extensions/pagetop-bootsier/src/theme/attrs/color.rs +++ b/extensions/pagetop-bootsier/src/theme/attrs/color.rs @@ -44,7 +44,7 @@ impl Color { /// # Ejemplos /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// assert_eq!(Color::Primary.to_class(), "primary"); /// assert_eq!(Color::Danger.to_class(), "danger"); /// ``` @@ -124,7 +124,7 @@ impl Opacity { /// # Ejemplos /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// assert_eq!(Opacity::Opaque.class_with(""), "opacity-100"); /// assert_eq!(Opacity::Half.class_with("bg"), "bg-opacity-50"); /// assert_eq!(Opacity::SemiTransparent.class_with("text"), "text-opacity-25"); @@ -156,7 +156,7 @@ impl Opacity { /// # Ejemplos /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// assert_eq!(Opacity::Opaque.to_class(), "opacity-100"); /// assert_eq!(Opacity::Half.to_class(), "opacity-50"); /// assert_eq!(Opacity::Default.to_class(), ""); @@ -237,7 +237,7 @@ impl ColorBg { /// # Ejemplos /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// assert_eq!(ColorBg::Body.to_class(), "bg-body"); /// assert_eq!(ColorBg::Theme(Color::Primary).to_class(), "bg-primary"); /// assert_eq!(ColorBg::Subtle(Color::Warning).to_class(), "bg-warning-subtle"); @@ -321,7 +321,7 @@ impl ColorText { /// # Ejemplos /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// assert_eq!(ColorText::Body.to_class(), "text-body"); /// assert_eq!(ColorText::Theme(Color::Primary).to_class(), "text-primary"); /// assert_eq!(ColorText::Emphasis(Color::Danger).to_class(), "text-danger-emphasis"); diff --git a/extensions/pagetop-bootsier/src/theme/attrs/layout.rs b/extensions/pagetop-bootsier/src/theme/attrs/layout.rs index 81b07834..a1255dc0 100644 --- a/extensions/pagetop-bootsier/src/theme/attrs/layout.rs +++ b/extensions/pagetop-bootsier/src/theme/attrs/layout.rs @@ -61,7 +61,7 @@ impl ScaleSize { /// # Ejemplo /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// assert_eq!(ScaleSize::Auto.class_with("border"), "border"); /// assert_eq!(ScaleSize::Zero.class_with("m"), "m-0"); /// assert_eq!(ScaleSize::Three.class_with("p"), "p-3"); diff --git a/extensions/pagetop-bootsier/src/theme/attrs/rounded.rs b/extensions/pagetop-bootsier/src/theme/attrs/rounded.rs index 2a959767..69976142 100644 --- a/extensions/pagetop-bootsier/src/theme/attrs/rounded.rs +++ b/extensions/pagetop-bootsier/src/theme/attrs/rounded.rs @@ -71,7 +71,7 @@ impl RoundedRadius { /// # Ejemplos /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// assert_eq!(RoundedRadius::Scale2.class_with(""), "rounded-2"); /// assert_eq!(RoundedRadius::Zero.class_with("rounded-top"), "rounded-top-0"); /// assert_eq!(RoundedRadius::Scale3.class_with("rounded-top-end"), "rounded-top-end-3"); @@ -103,7 +103,7 @@ impl RoundedRadius { /// # Ejemplos /// /// ```rust - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// assert_eq!(RoundedRadius::Default.to_class(), "rounded"); /// assert_eq!(RoundedRadius::Zero.to_class(), "rounded-0"); /// assert_eq!(RoundedRadius::Scale3.to_class(), "rounded-3"); diff --git a/extensions/pagetop-bootsier/src/theme/button.rs b/extensions/pagetop-bootsier/src/theme/button.rs index e494c1df..48eb7283 100644 --- a/extensions/pagetop-bootsier/src/theme/button.rs +++ b/extensions/pagetop-bootsier/src/theme/button.rs @@ -19,9 +19,8 @@ use crate::theme::{ButtonAction, ButtonColor, ButtonSize}; /// # Ejemplo /// /// ```rust -/// use pagetop::prelude::*; -/// use pagetop_bootsier::theme::*; -/// +/// # use pagetop::prelude::*; +/// # use pagetop_bootsier::prelude::*; /// let save = Button::submit(L10n::n("Save")) /// .with_color(ButtonColor::Background(Color::Primary)); /// diff --git a/extensions/pagetop-bootsier/src/theme/classes/border.rs b/extensions/pagetop-bootsier/src/theme/classes/border.rs index bfa65522..8a6bd6c4 100644 --- a/extensions/pagetop-bootsier/src/theme/classes/border.rs +++ b/extensions/pagetop-bootsier/src/theme/classes/border.rs @@ -26,33 +26,45 @@ use crate::theme::attrs::{BorderColor, Opacity, ScaleSize, Side}; /// /// # Ejemplos /// +/// **Borde global:** /// ```rust -/// use pagetop_bootsier::theme::*; -/// -/// // Borde global. +/// # use pagetop_bootsier::prelude::*; /// let b = classes::Border::with(ScaleSize::Two); /// assert_eq!(b.to_class(), "border-2"); +/// ``` /// -/// // Aditivo (sólo borde superior): +/// **Aditivo (solo borde superior):** +/// ```rust +/// # use pagetop_bootsier::prelude::*; /// let b = classes::Border::default().with_side(Side::Top, ScaleSize::One); /// assert_eq!(b.to_class(), "border-top-1"); +/// ``` /// -/// // Sustractivo (borde global menos el superior): +/// **Sustractivo (borde global menos el superior):** +/// ```rust +/// # use pagetop_bootsier::prelude::*; /// let b = classes::Border::new().with_side(Side::Top, ScaleSize::Zero); /// assert_eq!(b.to_class(), "border border-top-0"); +/// ``` /// -/// // Ancho por lado (lado lógico inicial a 2 y final a 4): +/// **Ancho por lado (lado lógico inicial a 2 y final a 4):** +/// ```rust +/// # use pagetop_bootsier::prelude::*; /// let b = classes::Border::default() /// .with_side(Side::Start, ScaleSize::Two) /// .with_side(Side::End, ScaleSize::Four); /// assert_eq!(b.to_class(), "border-end-4 border-start-2"); +/// ``` /// -/// // Combinado (ejemplo completo): +/// **Combinado (ejemplo completo):** +/// ```rust +/// # use pagetop_bootsier::prelude::*; /// let b = classes::Border::new() // Borde por defecto. /// .with_side(Side::Top, ScaleSize::Zero) // Quita borde superior. /// .with_side(Side::End, ScaleSize::Three) // Ancho 3 para el lado lógico final. /// .with_color(BorderColor::Theme(Color::Primary)) /// .with_opacity(Opacity::Half); +/// /// assert_eq!(b.to_class(), "border border-top-0 border-end-3 border-primary border-opacity-50"); /// ``` #[rustfmt::skip] @@ -146,7 +158,7 @@ impl Border { /// # Ejemplos /// /// ```rust -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// // Convertir explícitamente con `From::from`: /// let b = classes::Border::from(ScaleSize::Two); /// assert_eq!(b.to_class(), "border-2"); diff --git a/extensions/pagetop-bootsier/src/theme/classes/color.rs b/extensions/pagetop-bootsier/src/theme/classes/color.rs index 10638a52..4776ca9f 100644 --- a/extensions/pagetop-bootsier/src/theme/classes/color.rs +++ b/extensions/pagetop-bootsier/src/theme/classes/color.rs @@ -9,8 +9,7 @@ use crate::theme::attrs::{ColorBg, ColorText, Opacity}; /// # Ejemplos /// /// ``` -/// use pagetop_bootsier::theme::*; -/// +/// # use pagetop_bootsier::prelude::*; /// // Sin clases. /// let s = classes::Background::new(); /// assert_eq!(s.to_class(), ""); @@ -91,7 +90,7 @@ impl From<(ColorBg, Opacity)> for Background { /// # Ejemplo /// /// ``` - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// let s: classes::Background = (ColorBg::White, Opacity::SemiTransparent).into(); /// assert_eq!(s.to_class(), "bg-white bg-opacity-25"); /// ``` @@ -106,7 +105,7 @@ impl From for Background { /// # Ejemplo /// /// ``` - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// let s: classes::Background = ColorBg::Black.into(); /// assert_eq!(s.to_class(), "bg-black"); /// ``` @@ -122,8 +121,7 @@ impl From for Background { /// # Ejemplos /// /// ``` -/// use pagetop_bootsier::theme::*; -/// +/// # use pagetop_bootsier::prelude::*; /// // Sin clases. /// let s = classes::Text::new(); /// assert_eq!(s.to_class(), ""); @@ -204,7 +202,7 @@ impl From<(ColorText, Opacity)> for Text { /// # Ejemplo /// /// ``` - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// let s: classes::Text = (ColorText::Theme(Color::Danger), Opacity::Opaque).into(); /// assert_eq!(s.to_class(), "text-danger text-opacity-100"); /// ``` @@ -220,7 +218,7 @@ impl From for Text { /// # Ejemplo /// /// ``` - /// # use pagetop_bootsier::theme::*; + /// # use pagetop_bootsier::prelude::*; /// let s: classes::Text = ColorText::Black.into(); /// assert_eq!(s.to_class(), "text-black"); /// ``` diff --git a/extensions/pagetop-bootsier/src/theme/classes/layout.rs b/extensions/pagetop-bootsier/src/theme/classes/layout.rs index ee403a88..2a927acc 100644 --- a/extensions/pagetop-bootsier/src/theme/classes/layout.rs +++ b/extensions/pagetop-bootsier/src/theme/classes/layout.rs @@ -10,8 +10,7 @@ use crate::theme::BreakPoint; /// # Ejemplos /// /// ```rust -/// use pagetop_bootsier::theme::*; -/// +/// # use pagetop_bootsier::prelude::*; /// let m = classes::Margin::with(Side::Top, ScaleSize::Three); /// assert_eq!(m.to_class(), "mt-3"); /// @@ -98,8 +97,7 @@ impl Margin { /// # Ejemplos /// /// ```rust -/// use pagetop_bootsier::theme::*; -/// +/// # use pagetop_bootsier::prelude::*; /// let p = classes::Padding::with(Side::LeftAndRight, ScaleSize::Two); /// assert_eq!(p.to_class(), "px-2"); /// diff --git a/extensions/pagetop-bootsier/src/theme/classes/rounded.rs b/extensions/pagetop-bootsier/src/theme/classes/rounded.rs index 9fcb544e..16213e01 100644 --- a/extensions/pagetop-bootsier/src/theme/classes/rounded.rs +++ b/extensions/pagetop-bootsier/src/theme/classes/rounded.rs @@ -14,30 +14,42 @@ use crate::theme::attrs::RoundedRadius; /// /// # Ejemplos /// +/// **Radio global:** /// ```rust -/// use pagetop_bootsier::theme::*; -/// -/// // Radio global: +/// # use pagetop_bootsier::prelude::*; /// let r = classes::Rounded::with(RoundedRadius::Default); /// assert_eq!(r.to_class(), "rounded"); +/// ``` /// -/// // Sin redondeo: +/// **Sin redondeo:** +/// ```rust +/// # use pagetop_bootsier::prelude::*; /// let r = classes::Rounded::new(); /// assert_eq!(r.to_class(), ""); +/// ``` /// -/// // Radio en las esquinas de un lado lógico: +/// **Radio en las esquinas de un lado lógico:** +/// ```rust +/// # use pagetop_bootsier::prelude::*; /// let r = classes::Rounded::new().with_end(RoundedRadius::Scale2); /// assert_eq!(r.to_class(), "rounded-end-2"); +/// ``` /// -/// // Radio en una esquina concreta: +/// **Radio en una esquina concreta:** +/// ```rust +/// # use pagetop_bootsier::prelude::*; /// let r = classes::Rounded::new().with_top_start(RoundedRadius::Scale3); /// assert_eq!(r.to_class(), "rounded-top-start-3"); +/// ``` /// -/// // Combinado (ejemplo completo): +/// **Combinado (ejemplo completo):** +/// ```rust +/// # use pagetop_bootsier::prelude::*; /// let r = classes::Rounded::new() /// .with_top(RoundedRadius::Default) // Añade redondeo arriba. /// .with_bottom_start(RoundedRadius::Scale4) // Añade una esquina redondeada concreta. /// .with_bottom_end(RoundedRadius::Circle); // Añade redondeo extremo en otra esquina. +/// /// assert_eq!(r.to_class(), "rounded-top rounded-bottom-start-4 rounded-bottom-end-circle"); /// ``` #[rustfmt::skip] diff --git a/extensions/pagetop-bootsier/src/theme/container.rs b/extensions/pagetop-bootsier/src/theme/container.rs index 707fdc4f..a860110f 100644 --- a/extensions/pagetop-bootsier/src/theme/container.rs +++ b/extensions/pagetop-bootsier/src/theme/container.rs @@ -6,6 +6,16 @@ //! Con [`container::Width`](crate::theme::container::Width) se puede definir el ancho y el //! comportamiento *responsive* del contenedor. También permite aplicar utilidades de estilo para el //! fondo, texto, borde o esquinas redondeadas. +//! +//! # Ejemplo +//! +//! ```rust +//! # use pagetop::prelude::*; +//! # use pagetop_bootsier::prelude::*; +//! let main = Container::main() +//! .with_id("main-page") +//! .with_width(container::Width::From(BreakPoint::LG)); +//! ``` mod props; pub use props::{Kind, Width}; diff --git a/extensions/pagetop-bootsier/src/theme/container/component.rs b/extensions/pagetop-bootsier/src/theme/container/component.rs index 9e4e33c0..0635ad18 100644 --- a/extensions/pagetop-bootsier/src/theme/container/component.rs +++ b/extensions/pagetop-bootsier/src/theme/container/component.rs @@ -1,23 +1,11 @@ use pagetop::prelude::*; -use crate::theme::*; +use crate::prelude::*; -/// Componente para crear un **contenedor de componentes** ([`container`]). +/// Componente para crear un **contenedor de componentes**. /// -/// Envuelve un conjunto de componentes en un contenedor establecido que se crea aplicando uno de -/// los tipos definidos en [`container::Kind`]. -/// -/// Si no contiene elementos, el componente **no se renderiza**. -/// -/// # Ejemplo -/// -/// ```rust -/// use pagetop_bootsier::theme::*; -/// -/// let main = Container::main() -/// .with_id("main-page") -/// .with_width(container::Width::From(BreakPoint::LG)); -/// ``` +/// Envuelve un contenido con la etiqueta HTML indicada por [`container::Kind`]. Sólo se renderiza +/// si existen componentes hijos (*children*). #[derive(AutoDefault, Clone, Debug, Getters)] pub struct Container { #[getters(skip)] diff --git a/extensions/pagetop-bootsier/src/theme/dropdown.rs b/extensions/pagetop-bootsier/src/theme/dropdown.rs index c8e27870..213756c7 100644 --- a/extensions/pagetop-bootsier/src/theme/dropdown.rs +++ b/extensions/pagetop-bootsier/src/theme/dropdown.rs @@ -1,4 +1,4 @@ -//! Definiciones para crear menús desplegables ([`Dropdown`]). +//! Definiciones para crear menús desplegables [`Dropdown`]. //! //! Cada [`dropdown::Item`](crate::theme::dropdown::Item) representa un elemento individual del //! desplegable [`Dropdown`], con distintos comportamientos según su finalidad, como enlaces de @@ -6,6 +6,23 @@ //! //! Los ítems pueden estar activos, deshabilitados o abrirse en nueva ventana según su contexto y //! configuración, y permiten incluir etiquetas localizables usando [`L10n`](pagetop::locale::L10n). +//! +//! # Ejemplo +//! +//! ```rust +//! # use pagetop::prelude::*; +//! # use pagetop_bootsier::prelude::*; +//! let dd = Dropdown::new() +//! .with_title(L10n::n("Menu")) +//! .with_button_color(ButtonColor::Background(Color::Secondary)) +//! .with_auto_close(dropdown::AutoClose::ClickableInside) +//! .with_direction(dropdown::Direction::Dropend) +//! .with_item(dropdown::Item::link(L10n::n("Home"), |_| "/".into())) +//! .with_item(dropdown::Item::link_blank(L10n::n("External"), |_| "https://docs.rs".into())) +//! .with_item(dropdown::Item::divider()) +//! .with_item(dropdown::Item::header(L10n::n("User session"))) +//! .with_item(dropdown::Item::button(L10n::n("Sign out"))); +//! ``` mod props; pub use props::{AutoClose, Direction, MenuAlign, MenuPosition}; diff --git a/extensions/pagetop-bootsier/src/theme/dropdown/component.rs b/extensions/pagetop-bootsier/src/theme/dropdown/component.rs index ca15c635..833cf40b 100644 --- a/extensions/pagetop-bootsier/src/theme/dropdown/component.rs +++ b/extensions/pagetop-bootsier/src/theme/dropdown/component.rs @@ -1,14 +1,14 @@ use pagetop::prelude::*; -use crate::theme::*; +use crate::prelude::*; use crate::LOCALES_BOOTSIER; -/// Componente para crear un **menú desplegable** ([`dropdown`]). +/// Componente para crear un **menú desplegable**. /// /// Renderiza un botón (único o desdoblado, ver [`with_button_split()`](Self::with_button_split)) -/// para mostrar un menú desplegable de elementos [`dropdown::Item`], que se muestra u oculta según -/// la interacción del usuario. Admite variaciones para el tamaño y el color del botón, también para -/// la dirección de apertura, alineación o política de cierre. +/// para mostrar un menú desplegable de elementos [`dropdown::Item`], que se muestra/oculta según la +/// interacción del usuario. Admite variaciones de tamaño/color del botón, también dirección de +/// apertura, alineación o política de cierre. /// /// Si no tiene título (ver [`with_title()`](Self::with_title)) se muestra únicamente la lista de /// elementos sin ningún botón para interactuar. @@ -17,25 +17,8 @@ use crate::LOCALES_BOOTSIER; /// cuenta **el título** (si no existe le asigna uno por defecto) y **la lista de elementos**; el /// resto de propiedades no afectarán a su representación en [`Nav`]. /// +/// Ver ejemplo en el módulo [`dropdown`]. /// Si no contiene elementos, el componente **no se renderiza**. -/// -/// # Ejemplo -/// -/// ```rust -/// use pagetop::prelude::*; -/// use pagetop_bootsier::theme::*; -/// -/// let dd = Dropdown::new() -/// .with_title(L10n::n("Menu")) -/// .with_button_color(ButtonColor::Background(Color::Secondary)) -/// .with_auto_close(dropdown::AutoClose::ClickableInside) -/// .with_direction(dropdown::Direction::Dropend) -/// .with_item(dropdown::Item::link(L10n::n("Home"), |_| "/".into())) -/// .with_item(dropdown::Item::link_blank(L10n::n("External"), |_| "https://docs.rs".into())) -/// .with_item(dropdown::Item::divider()) -/// .with_item(dropdown::Item::header(L10n::n("User session"))) -/// .with_item(dropdown::Item::button(L10n::n("Sign out"))); -/// ``` #[derive(AutoDefault, Clone, Debug, Getters)] pub struct Dropdown { #[getters(skip)] diff --git a/extensions/pagetop-bootsier/src/theme/dropdown/props.rs b/extensions/pagetop-bootsier/src/theme/dropdown/props.rs index fb11783d..fd315508 100644 --- a/extensions/pagetop-bootsier/src/theme/dropdown/props.rs +++ b/extensions/pagetop-bootsier/src/theme/dropdown/props.rs @@ -1,6 +1,6 @@ use pagetop::prelude::*; -use crate::theme::*; +use crate::prelude::*; // **< AutoClose >********************************************************************************** diff --git a/extensions/pagetop-bootsier/src/theme/form.rs b/extensions/pagetop-bootsier/src/theme/form.rs index 82c603ef..634dc48a 100644 --- a/extensions/pagetop-bootsier/src/theme/form.rs +++ b/extensions/pagetop-bootsier/src/theme/form.rs @@ -1,4 +1,36 @@ //! Definiciones para crear formularios ([`Form`]). +//! +//! # Ejemplo +//! +//! ```rust +//! use pagetop::prelude::*; +//! use pagetop_bootsier::prelude::*; +//! +//! let form_login = Form::new() +//! .with_id("login") +//! .with_action("/login") +//! .with_child( +//! form::input::Field::email() +//! .with_name("email") +//! .with_label(L10n::n("Email")) +//! .with_required(true), +//! ) +//! .with_child( +//! form::input::Field::password() +//! .with_name("password") +//! .with_label(L10n::n("Password")) +//! .with_required(true), +//! ) +//! .with_child( +//! form::Checkbox::check() +//! .with_name("remember") +//! .with_label(L10n::n("Remember me")), +//! ) +//! .with_child( +//! Button::submit(L10n::n("Sign in")) +//! .with_color(ButtonColor::Background(Color::Primary)), +//! ); +//! ``` mod props; pub use props::{Autocomplete, AutofillField, CheckboxKind, Method}; diff --git a/extensions/pagetop-bootsier/src/theme/form/check.rs b/extensions/pagetop-bootsier/src/theme/form/check.rs index 434b7e6c..824ed92a 100644 --- a/extensions/pagetop-bootsier/src/theme/form/check.rs +++ b/extensions/pagetop-bootsier/src/theme/form/check.rs @@ -17,7 +17,7 @@ use pagetop::prelude::*; /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let item = form::check::Item::new("apple", L10n::n("Apple")).with_checked(true); /// ``` #[derive(AutoDefault, Clone, Debug, Getters)] @@ -82,7 +82,7 @@ impl Item { /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let interests = form::check::Field::new() /// .with_name("interests") /// .with_label(L10n::n("Areas of interest")) diff --git a/extensions/pagetop-bootsier/src/theme/form/checkbox.rs b/extensions/pagetop-bootsier/src/theme/form/checkbox.rs index 60d7120d..6206d983 100644 --- a/extensions/pagetop-bootsier/src/theme/form/checkbox.rs +++ b/extensions/pagetop-bootsier/src/theme/form/checkbox.rs @@ -17,7 +17,7 @@ use crate::LOCALES_BOOTSIER; /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let accept_terms = form::Checkbox::check() // También sirve new() o default(). /// .with_name("terms_accepted") /// .with_label(L10n::n("I accept the terms and conditions")) diff --git a/extensions/pagetop-bootsier/src/theme/form/component.rs b/extensions/pagetop-bootsier/src/theme/form/component.rs index 80efa941..e4c22a56 100644 --- a/extensions/pagetop-bootsier/src/theme/form/component.rs +++ b/extensions/pagetop-bootsier/src/theme/form/component.rs @@ -2,9 +2,9 @@ use pagetop::prelude::*; use crate::theme::form; -/// Componente para crear un **formulario** ([`form`]). +/// Componente para crear un **formulario**. /// -/// Este componente renderiza un formulario estándar con soporte para los atributos más habituales: +/// Este componente renderiza un `
` estándar con soporte para los atributos más habituales: /// /// - `id`: identificador opcional del formulario. /// - `classes`: clases CSS adicionales (p. ej. utilidades CSS). @@ -17,33 +17,13 @@ use crate::theme::form; /// # Ejemplo /// /// ```rust -/// use pagetop::prelude::*; -/// use pagetop_bootsier::theme::*; -/// -/// let form_login = Form::new() -/// .with_id("login") -/// .with_action("/login") -/// .with_child( -/// form::input::Field::email() -/// .with_name("email") -/// .with_label(L10n::n("Email")) -/// .with_required(true), -/// ) -/// .with_child( -/// form::input::Field::password() -/// .with_name("password") -/// .with_label(L10n::n("Password")) -/// .with_required(true), -/// ) -/// .with_child( -/// form::Checkbox::check() -/// .with_name("remember") -/// .with_label(L10n::n("Remember me")), -/// ) -/// .with_child( -/// Button::submit(L10n::n("Sign in")) -/// .with_color(ButtonColor::Background(Color::Primary)), -/// ); +/// # use pagetop::prelude::*; +/// # use pagetop_bootsier::prelude::*; +/// let search = Form::new() +/// .with_id("search") +/// .with_action("/search") +/// .with_method(form::Method::Get) +/// .with_child(form::input::Field::search().with_name("q")); /// ``` #[derive(AutoDefault, Clone, Debug, Getters)] pub struct Form { diff --git a/extensions/pagetop-bootsier/src/theme/form/fieldset.rs b/extensions/pagetop-bootsier/src/theme/form/fieldset.rs index 1aacba6c..b5d0e822 100644 --- a/extensions/pagetop-bootsier/src/theme/form/fieldset.rs +++ b/extensions/pagetop-bootsier/src/theme/form/fieldset.rs @@ -15,7 +15,7 @@ use pagetop::prelude::*; /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let personal_data = form::Fieldset::new() /// .with_legend(L10n::n("Personal data")) /// .with_description(L10n::n("Enter your full name and contact email.")) diff --git a/extensions/pagetop-bootsier/src/theme/form/hidden.rs b/extensions/pagetop-bootsier/src/theme/form/hidden.rs index 6d367155..61d24547 100644 --- a/extensions/pagetop-bootsier/src/theme/form/hidden.rs +++ b/extensions/pagetop-bootsier/src/theme/form/hidden.rs @@ -12,7 +12,7 @@ use pagetop::prelude::*; /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let token = form::Hidden::new() /// .with_name("csrf_token") /// .with_value("a1b2c3d4e5"); diff --git a/extensions/pagetop-bootsier/src/theme/form/input.rs b/extensions/pagetop-bootsier/src/theme/form/input.rs index 997b7c45..a6dc34ea 100644 --- a/extensions/pagetop-bootsier/src/theme/form/input.rs +++ b/extensions/pagetop-bootsier/src/theme/form/input.rs @@ -106,7 +106,7 @@ impl fmt::Display for Mode { /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let email = form::input::Field::email() /// .with_name("email") /// .with_label(L10n::n("Email address")) diff --git a/extensions/pagetop-bootsier/src/theme/form/props.rs b/extensions/pagetop-bootsier/src/theme/form/props.rs index 2ef88f3e..dbd1e705 100644 --- a/extensions/pagetop-bootsier/src/theme/form/props.rs +++ b/extensions/pagetop-bootsier/src/theme/form/props.rs @@ -52,7 +52,7 @@ pub enum CheckboxKind { /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// // Correo electrónico con sugerencia semántica del navegador. /// let ac = form::Autocomplete::email(); /// @@ -244,7 +244,7 @@ impl fmt::Display for Autocomplete { /// # Ejemplo /// /// ```rust -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let ac = form::Autocomplete::token(form::AutofillField::Username); /// let ac = form::Autocomplete::shipping(form::AutofillField::StreetAddress); /// let ac = form::Autocomplete::section("job", form::AutofillField::Email); diff --git a/extensions/pagetop-bootsier/src/theme/form/radio.rs b/extensions/pagetop-bootsier/src/theme/form/radio.rs index d79c4f44..2514c4bf 100644 --- a/extensions/pagetop-bootsier/src/theme/form/radio.rs +++ b/extensions/pagetop-bootsier/src/theme/form/radio.rs @@ -16,7 +16,7 @@ use crate::LOCALES_BOOTSIER; /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let item = form::radio::Item::new("monthly", L10n::n("Monthly")).with_checked(true); /// ``` #[derive(AutoDefault, Clone, Debug, Getters)] @@ -76,7 +76,7 @@ impl Item { /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let plan = form::radio::Field::new() /// .with_name("plan") /// .with_label(L10n::n("Subscription plan")) diff --git a/extensions/pagetop-bootsier/src/theme/form/range.rs b/extensions/pagetop-bootsier/src/theme/form/range.rs index 45d07acf..40350479 100644 --- a/extensions/pagetop-bootsier/src/theme/form/range.rs +++ b/extensions/pagetop-bootsier/src/theme/form/range.rs @@ -10,7 +10,7 @@ use pagetop::prelude::*; /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let volume = form::Range::new() /// .with_name("volume") /// .with_label(L10n::n("Volume")) diff --git a/extensions/pagetop-bootsier/src/theme/form/select.rs b/extensions/pagetop-bootsier/src/theme/form/select.rs index 92736586..1fa74f09 100644 --- a/extensions/pagetop-bootsier/src/theme/form/select.rs +++ b/extensions/pagetop-bootsier/src/theme/form/select.rs @@ -20,7 +20,7 @@ use crate::LOCALES_BOOTSIER; /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let item = form::select::Item::new("es", L10n::n("Spanish")).with_selected(true); /// ``` #[derive(AutoDefault, Clone, Debug, Getters)] @@ -76,7 +76,7 @@ impl Item { /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let group = form::select::Group::new(L10n::n("Europe")) /// .with_item(form::select::Item::new("es", L10n::n("Spanish"))) /// .with_item(form::select::Item::new("fr", L10n::n("French"))); @@ -149,7 +149,7 @@ pub enum Entry { /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let idioma = form::select::Field::new() /// .with_name("language") /// .with_label(L10n::n("Language")) diff --git a/extensions/pagetop-bootsier/src/theme/form/textarea.rs b/extensions/pagetop-bootsier/src/theme/form/textarea.rs index 781e1d09..c545df8c 100644 --- a/extensions/pagetop-bootsier/src/theme/form/textarea.rs +++ b/extensions/pagetop-bootsier/src/theme/form/textarea.rs @@ -13,7 +13,7 @@ use crate::LOCALES_BOOTSIER; /// /// ```rust /// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; +/// # use pagetop_bootsier::prelude::*; /// let descripcion = form::Textarea::new() /// .with_name("description") /// .with_label(L10n::n("Description")) diff --git a/extensions/pagetop-bootsier/src/theme/icon.rs b/extensions/pagetop-bootsier/src/theme/icon.rs index 9ef6aeee..935aa847 100644 --- a/extensions/pagetop-bootsier/src/theme/icon.rs +++ b/extensions/pagetop-bootsier/src/theme/icon.rs @@ -1,4 +1,4 @@ -use crate::theme::*; +use crate::prelude::*; const DEFAULT_VIEWBOX: &str = "0 0 16 16"; diff --git a/extensions/pagetop-bootsier/src/theme/image/component.rs b/extensions/pagetop-bootsier/src/theme/image/component.rs index 678ccdb3..898fb573 100644 --- a/extensions/pagetop-bootsier/src/theme/image/component.rs +++ b/extensions/pagetop-bootsier/src/theme/image/component.rs @@ -1,16 +1,14 @@ use pagetop::prelude::*; -use crate::theme::*; +use crate::prelude::*; -/// Componente para renderizar una **imagen** ([`image`]). +/// Componente para renderizar una **imagen**. /// -/// A una imagen se le puede: -/// -/// - Establecer su contenido a partir del origen definido en [`image::Source`]. -/// - Configurar sus **dimensiones** ([`with_size()`](Self::with_size)), **borde** +/// - Ajusta su disposición según el origen definido en [`image::Source`]. +/// - Permite configurar **dimensiones** ([`with_size()`](Self::with_size)), **borde** /// ([`classes::Border`](crate::theme::classes::Border)) y **redondeo de esquinas** /// ([`classes::Rounded`](crate::theme::classes::Rounded)). -/// - Aplicar el texto alternativo `alt` con **localización** mediante [`L10n`]. +/// - Resuelve el texto alternativo `alt` con **localización** mediante [`L10n`]. #[derive(AutoDefault, Clone, Debug, Getters)] pub struct Image { #[getters(skip)] diff --git a/extensions/pagetop-bootsier/src/theme/nav.rs b/extensions/pagetop-bootsier/src/theme/nav.rs index 74e9214d..16b3d2d7 100644 --- a/extensions/pagetop-bootsier/src/theme/nav.rs +++ b/extensions/pagetop-bootsier/src/theme/nav.rs @@ -1,4 +1,4 @@ -//! Definiciones para crear menús ([`Nav`]). +//! Definiciones para crear menús [`Nav`] o alguna de sus variantes de presentación. //! //! Cada [`nav::Item`](crate::theme::nav::Item) representa un elemento individual del menú [`Nav`], //! con distintos comportamientos según su finalidad, como enlaces de navegación o menús @@ -6,6 +6,26 @@ //! //! Los ítems pueden estar activos, deshabilitados o abrirse en nueva ventana según su contexto y //! configuración, y permiten incluir etiquetas localizables usando [`L10n`](pagetop::locale::L10n). +//! +//! # Ejemplo +//! +//! ```rust +//! # use pagetop::prelude::*; +//! # use pagetop_bootsier::prelude::*; +//! let nav = Nav::tabs() +//! .with_layout(nav::Layout::End) +//! .with_item(nav::Item::link(L10n::n("Home"), |_| "/".into())) +//! .with_item(nav::Item::link_blank(L10n::n("External"), |_| "https://docs.rs".into())) +//! .with_item(nav::Item::dropdown( +//! Dropdown::new() +//! .with_title(L10n::n("Options")) +//! .with_item(ChildOp::AddMany(vec![ +//! dropdown::Item::link(L10n::n("Action"), |_| "/action".into()).into(), +//! dropdown::Item::link(L10n::n("Another"), |_| "/another".into()).into(), +//! ])), +//! )) +//! .with_item(nav::Item::link_disabled(L10n::n("Disabled"), |_| "#".into())); +//! ``` mod props; pub use props::{Kind, Layout}; diff --git a/extensions/pagetop-bootsier/src/theme/nav/component.rs b/extensions/pagetop-bootsier/src/theme/nav/component.rs index aeb0447e..0b7797c8 100644 --- a/extensions/pagetop-bootsier/src/theme/nav/component.rs +++ b/extensions/pagetop-bootsier/src/theme/nav/component.rs @@ -1,35 +1,15 @@ use pagetop::prelude::*; -use crate::theme::*; +use crate::prelude::*; -/// Componente para crear un **menú** ([`nav`]). +/// Componente para crear un **menú** o alguna de sus variantes ([`nav::Kind`]). /// /// Presenta un menú con una lista de elementos usando una vista básica, o alguna de sus variantes -/// ([`nav::Kind`]) como *pestañas* (`Tabs`), *botones* (`Pills`) o *subrayado* (`Underline`). -/// También permite controlar su distribución y orientación ([`nav::Layout`](crate::theme::nav::Layout)). +/// como *pestañas* (`Tabs`), *botones* (`Pills`) o *subrayado* (`Underline`). También permite +/// controlar su distribución y orientación ([`nav::Layout`](crate::theme::nav::Layout)). /// +/// Ver ejemplo en el módulo [`nav`]. /// Si no contiene elementos, el componente **no se renderiza**. -/// -/// # Ejemplo -/// -/// ```rust -/// use pagetop::prelude::*; -/// use pagetop_bootsier::theme::*; -/// -/// let nav = Nav::tabs() -/// .with_layout(nav::Layout::End) -/// .with_item(nav::Item::link(L10n::n("Home"), |_| "/".into())) -/// .with_item(nav::Item::link_blank(L10n::n("External"), |_| "https://docs.rs".into())) -/// .with_item(nav::Item::dropdown( -/// Dropdown::new() -/// .with_title(L10n::n("Options")) -/// .with_item(ChildOp::AddMany(vec![ -/// dropdown::Item::link(L10n::n("Action"), |_| "/action".into()).into(), -/// dropdown::Item::link(L10n::n("Another"), |_| "/another".into()).into(), -/// ])), -/// )) -/// .with_item(nav::Item::link_disabled(L10n::n("Disabled"), |_| "#".into())); -/// ``` #[derive(AutoDefault, Clone, Debug, Getters)] pub struct Nav { #[getters(skip)] diff --git a/extensions/pagetop-bootsier/src/theme/nav/item.rs b/extensions/pagetop-bootsier/src/theme/nav/item.rs index ef5a6fe9..956ccdcd 100644 --- a/extensions/pagetop-bootsier/src/theme/nav/item.rs +++ b/extensions/pagetop-bootsier/src/theme/nav/item.rs @@ -1,6 +1,6 @@ use pagetop::prelude::*; -use crate::theme::*; +use crate::prelude::*; use crate::LOCALES_BOOTSIER; // **< ItemKind >*********************************************************************************** diff --git a/extensions/pagetop-bootsier/src/theme/navbar.rs b/extensions/pagetop-bootsier/src/theme/navbar.rs index f381b1f3..31a16ccc 100644 --- a/extensions/pagetop-bootsier/src/theme/navbar.rs +++ b/extensions/pagetop-bootsier/src/theme/navbar.rs @@ -1,4 +1,4 @@ -//! Definiciones para crear barras de navegación ([`Navbar`]). +//! Definiciones para crear barras de navegación [`Navbar`]. //! //! Cada [`navbar::Item`](crate::theme::navbar::Item) representa un elemento individual de la barra //! de navegación [`Navbar`], con distintos comportamientos según su finalidad, como menús @@ -6,6 +6,126 @@ //! //! También puede mostrar una marca de identidad ([`navbar::Brand`](crate::theme::navbar::Brand)) //! que identifique la compañía, producto o nombre del proyecto asociado a la solución web. +//! +//! # Ejemplos +//! +//! Barra **simple**, sólo con un menú horizontal: +//! +//! ```rust +//! # use pagetop::prelude::*; +//! # use pagetop_bootsier::prelude::*; +//! let navbar = Navbar::simple() +//! .with_item(navbar::Item::nav( +//! Nav::new() +//! .with_item(nav::Item::link(L10n::n("Home"), |_| "/".into())) +//! .with_item(nav::Item::link(L10n::n("About"), |_| "/about".into())) +//! .with_item(nav::Item::link(L10n::n("Contact"), |_| "/contact".into())) +//! )); +//! ``` +//! +//! Barra **colapsable**, con botón de despliegue y contenido en el desplegable cuando colapsa: +//! +//! ```rust +//! # use pagetop::prelude::*; +//! # use pagetop_bootsier::prelude::*; +//! let navbar = Navbar::simple_toggle() +//! .with_expand(BreakPoint::MD) +//! .with_item(navbar::Item::nav( +//! Nav::new() +//! .with_item(nav::Item::link(L10n::n("Home"), |_| "/".into())) +//! .with_item(nav::Item::link_blank(L10n::n("Docs"), |_| "https://docs.rs".into())) +//! .with_item(nav::Item::link(L10n::n("Support"), |_| "/support".into())) +//! )); +//! ``` +//! +//! Barra con **marca de identidad a la izquierda** y menú a la derecha, típica de una cabecera: +//! +//! ```rust +//! # use pagetop::prelude::*; +//! # use pagetop_bootsier::prelude::*; +//! let brand = navbar::Brand::new() +//! .with_title(L10n::n("PageTop")) +//! .with_route(Some(|cx| cx.route("/"))); +//! +//! let navbar = Navbar::brand_left(brand) +//! .with_item(navbar::Item::nav( +//! Nav::new() +//! .with_item(nav::Item::link(L10n::n("Home"), |_| "/".into())) +//! .with_item(nav::Item::dropdown( +//! Dropdown::new() +//! .with_title(L10n::n("Tools")) +//! .with_item(dropdown::Item::link( +//! L10n::n("Generator"), |_| "/tools/gen".into()) +//! ) +//! .with_item(dropdown::Item::link( +//! L10n::n("Reports"), |_| "/tools/reports".into()) +//! ) +//! )) +//! .with_item(nav::Item::link_disabled(L10n::n("Disabled"), |_| "#".into())) +//! )); +//! ``` +//! +//! Barra con **botón de despliegue a la izquierda** y **marca de identidad a la derecha**: +//! +//! ```rust +//! # use pagetop::prelude::*; +//! # use pagetop_bootsier::prelude::*; +//! let brand = navbar::Brand::new() +//! .with_title(L10n::n("Intranet")) +//! .with_route(Some(|cx| cx.route("/"))); +//! +//! let navbar = Navbar::brand_right(brand) +//! .with_expand(BreakPoint::LG) +//! .with_item(navbar::Item::nav( +//! Nav::pills() +//! .with_item(nav::Item::link(L10n::n("Dashboard"), |_| "/dashboard".into())) +//! .with_item(nav::Item::link(L10n::n("Users"), |_| "/users".into())) +//! )); +//! ``` +//! +//! Barra con el **contenido en un *offcanvas***, ideal para dispositivos móviles o menús largos: +//! +//! ```rust +//! # use pagetop::prelude::*; +//! # use pagetop_bootsier::prelude::*; +//! let oc = Offcanvas::new() +//! .with_id("main_offcanvas") +//! .with_title(L10n::n("Main menu")) +//! .with_placement(offcanvas::Placement::Start) +//! .with_backdrop(offcanvas::Backdrop::Enabled); +//! +//! let navbar = Navbar::offcanvas(oc) +//! .with_item(navbar::Item::nav( +//! Nav::new() +//! .with_item(nav::Item::link(L10n::n("Home"), |_| "/".into())) +//! .with_item(nav::Item::link(L10n::n("Profile"), |_| "/profile".into())) +//! .with_item(nav::Item::dropdown( +//! Dropdown::new() +//! .with_title(L10n::n("More")) +//! .with_item(dropdown::Item::link(L10n::n("Settings"), |_| "/settings".into())) +//! .with_item(dropdown::Item::link(L10n::n("Help"), |_| "/help".into())) +//! )) +//! )); +//! ``` +//! +//! Barra **fija arriba**: +//! +//! ```rust +//! # use pagetop::prelude::*; +//! # use pagetop_bootsier::prelude::*; +//! let brand = navbar::Brand::new() +//! .with_title(L10n::n("Main App")) +//! .with_route(Some(|cx| cx.route("/"))); +//! +//! let navbar = Navbar::brand_left(brand) +//! .with_position(navbar::Position::FixedTop) +//! .with_item(navbar::Item::nav( +//! Nav::new() +//! .with_item(nav::Item::link(L10n::n("Dashboard"), |_| "/".into())) +//! .with_item(nav::Item::link(L10n::n("Donors"), |_| "/donors".into())) +//! .with_item(nav::Item::link(L10n::n("Stock"), |_| "/stock".into())) +//! )); +//! ``` mod props; pub use props::{Layout, Position}; diff --git a/extensions/pagetop-bootsier/src/theme/navbar/brand.rs b/extensions/pagetop-bootsier/src/theme/navbar/brand.rs index 9e5082b6..4d575e03 100644 --- a/extensions/pagetop-bootsier/src/theme/navbar/brand.rs +++ b/extensions/pagetop-bootsier/src/theme/navbar/brand.rs @@ -1,6 +1,6 @@ use pagetop::prelude::*; -use crate::theme::*; +use crate::prelude::*; /// Marca de identidad para mostrar en una barra de navegación [`Navbar`]. /// diff --git a/extensions/pagetop-bootsier/src/theme/navbar/component.rs b/extensions/pagetop-bootsier/src/theme/navbar/component.rs index ccd97e90..33aa80de 100644 --- a/extensions/pagetop-bootsier/src/theme/navbar/component.rs +++ b/extensions/pagetop-bootsier/src/theme/navbar/component.rs @@ -1,139 +1,19 @@ use pagetop::prelude::*; -use crate::theme::*; +use crate::prelude::*; use crate::LOCALES_BOOTSIER; const TOGGLE_COLLAPSE: &str = "collapse"; const TOGGLE_OFFCANVAS: &str = "offcanvas"; -/// Componente para crear una **barra de navegación** ([`navbar`]). +/// Componente para crear una **barra de navegación**. /// /// Permite mostrar enlaces, menús y una marca de identidad en distintas disposiciones (simples, con /// botón de despliegue o dentro de un [`offcanvas`]), controladas por [`navbar::Layout`]. También /// puede fijarse en la parte superior o inferior del documento mediante [`navbar::Position`]. /// +/// Ver ejemplos en el módulo [`navbar`]. /// Si no contiene elementos, el componente **no se renderiza**. -/// -/// # Ejemplos -/// -/// Barra **simple**, sólo con un menú horizontal: -/// -/// ```rust -/// use pagetop::prelude::*; -/// use pagetop_bootsier::theme::*; -/// -/// let navbar = Navbar::simple() -/// .with_item(navbar::Item::nav( -/// Nav::new() -/// .with_item(nav::Item::link(L10n::n("Home"), |_| "/".into())) -/// .with_item(nav::Item::link(L10n::n("About"), |_| "/about".into())) -/// .with_item(nav::Item::link(L10n::n("Contact"), |_| "/contact".into())) -/// )); -/// ``` -/// -/// Barra **colapsable**, con botón de despliegue y contenido en el desplegable cuando colapsa: -/// -/// ```rust -/// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; -/// let navbar = Navbar::simple_toggle() -/// .with_expand(BreakPoint::MD) -/// .with_item(navbar::Item::nav( -/// Nav::new() -/// .with_item(nav::Item::link(L10n::n("Home"), |_| "/".into())) -/// .with_item(nav::Item::link_blank(L10n::n("Docs"), |_| "https://docs.rs".into())) -/// .with_item(nav::Item::link(L10n::n("Support"), |_| "/support".into())) -/// )); -/// ``` -/// -/// Barra con **marca de identidad a la izquierda** y menú a la derecha, típica de una cabecera: -/// -/// ```rust -/// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; -/// let brand = navbar::Brand::new() -/// .with_title(L10n::n("PageTop")) -/// .with_route(Some(|cx| cx.route("/"))); -/// -/// let navbar = Navbar::brand_left(brand) -/// .with_item(navbar::Item::nav( -/// Nav::new() -/// .with_item(nav::Item::link(L10n::n("Home"), |_| "/".into())) -/// .with_item(nav::Item::dropdown( -/// Dropdown::new() -/// .with_title(L10n::n("Tools")) -/// .with_item(dropdown::Item::link( -/// L10n::n("Generator"), |_| "/tools/gen".into()) -/// ) -/// .with_item(dropdown::Item::link( -/// L10n::n("Reports"), |_| "/tools/reports".into()) -/// ) -/// )) -/// .with_item(nav::Item::link_disabled(L10n::n("Disabled"), |_| "#".into())) -/// )); -/// ``` -/// -/// Barra con **botón de despliegue a la izquierda** y **marca de identidad a la derecha**: -/// -/// ```rust -/// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; -/// let brand = navbar::Brand::new() -/// .with_title(L10n::n("Intranet")) -/// .with_route(Some(|cx| cx.route("/"))); -/// -/// let navbar = Navbar::brand_right(brand) -/// .with_expand(BreakPoint::LG) -/// .with_item(navbar::Item::nav( -/// Nav::pills() -/// .with_item(nav::Item::link(L10n::n("Dashboard"), |_| "/dashboard".into())) -/// .with_item(nav::Item::link(L10n::n("Users"), |_| "/users".into())) -/// )); -/// ``` -/// -/// Barra con el **contenido en un *offcanvas***, ideal para dispositivos móviles o menús largos: -/// -/// ```rust -/// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; -/// let oc = Offcanvas::new() -/// .with_id("main_offcanvas") -/// .with_title(L10n::n("Main menu")) -/// .with_placement(offcanvas::Placement::Start) -/// .with_backdrop(offcanvas::Backdrop::Enabled); -/// -/// let navbar = Navbar::offcanvas(oc) -/// .with_item(navbar::Item::nav( -/// Nav::new() -/// .with_item(nav::Item::link(L10n::n("Home"), |_| "/".into())) -/// .with_item(nav::Item::link(L10n::n("Profile"), |_| "/profile".into())) -/// .with_item(nav::Item::dropdown( -/// Dropdown::new() -/// .with_title(L10n::n("More")) -/// .with_item(dropdown::Item::link(L10n::n("Settings"), |_| "/settings".into())) -/// .with_item(dropdown::Item::link(L10n::n("Help"), |_| "/help".into())) -/// )) -/// )); -/// ``` -/// -/// Barra **fija arriba**: -/// -/// ```rust -/// # use pagetop::prelude::*; -/// # use pagetop_bootsier::theme::*; -/// let brand = navbar::Brand::new() -/// .with_title(L10n::n("Main App")) -/// .with_route(Some(|cx| cx.route("/"))); -/// -/// let navbar = Navbar::brand_left(brand) -/// .with_position(navbar::Position::FixedTop) -/// .with_item(navbar::Item::nav( -/// Nav::new() -/// .with_item(nav::Item::link(L10n::n("Dashboard"), |_| "/".into())) -/// .with_item(nav::Item::link(L10n::n("Donors"), |_| "/donors".into())) -/// .with_item(nav::Item::link(L10n::n("Stock"), |_| "/stock".into())) -/// )); -/// ``` #[derive(AutoDefault, Clone, Debug, Getters)] pub struct Navbar { #[getters(skip)] diff --git a/extensions/pagetop-bootsier/src/theme/navbar/item.rs b/extensions/pagetop-bootsier/src/theme/navbar/item.rs index 9b48adf1..caba4e7d 100644 --- a/extensions/pagetop-bootsier/src/theme/navbar/item.rs +++ b/extensions/pagetop-bootsier/src/theme/navbar/item.rs @@ -1,6 +1,6 @@ use pagetop::prelude::*; -use crate::theme::*; +use crate::prelude::*; /// Elementos que puede contener una barra de navegación [`Navbar`](crate::theme::Navbar). /// diff --git a/extensions/pagetop-bootsier/src/theme/navbar/props.rs b/extensions/pagetop-bootsier/src/theme/navbar/props.rs index e0d64916..1ac248b7 100644 --- a/extensions/pagetop-bootsier/src/theme/navbar/props.rs +++ b/extensions/pagetop-bootsier/src/theme/navbar/props.rs @@ -1,6 +1,6 @@ use pagetop::prelude::*; -use crate::theme::*; +use crate::prelude::*; // **< Layout >************************************************************************************* diff --git a/extensions/pagetop-bootsier/src/theme/offcanvas.rs b/extensions/pagetop-bootsier/src/theme/offcanvas.rs index 63ecbc66..166893aa 100644 --- a/extensions/pagetop-bootsier/src/theme/offcanvas.rs +++ b/extensions/pagetop-bootsier/src/theme/offcanvas.rs @@ -1,4 +1,24 @@ -//! Definiciones para crear paneles laterales deslizantes ([`Offcanvas`]). +//! Definiciones para crear paneles laterales deslizantes [`Offcanvas`]. +//! +//! # Ejemplo +//! +//! ```rust +//! # use pagetop::prelude::*; +//! # use pagetop_bootsier::prelude::*; +//! let panel = Offcanvas::new() +//! .with_id("offcanvas_example") +//! .with_title(L10n::n("Offcanvas title")) +//! .with_placement(offcanvas::Placement::End) +//! .with_backdrop(offcanvas::Backdrop::Enabled) +//! .with_body_scroll(offcanvas::BodyScroll::Enabled) +//! .with_visibility(offcanvas::Visibility::Default) +//! .with_child(Dropdown::new() +//! .with_title(L10n::n("Menu")) +//! .with_item(dropdown::Item::label(L10n::n("Label"))) +//! .with_item(dropdown::Item::link_blank(L10n::n("Docs"), |_| "https://docs.rs".into())) +//! .with_item(dropdown::Item::link(L10n::n("Sign out"), |_| "/signout".into())) +//! ); +//! ``` mod props; pub use props::{Backdrop, BodyScroll, Placement, Visibility}; diff --git a/extensions/pagetop-bootsier/src/theme/offcanvas/component.rs b/extensions/pagetop-bootsier/src/theme/offcanvas/component.rs index 764627e4..88aad443 100644 --- a/extensions/pagetop-bootsier/src/theme/offcanvas/component.rs +++ b/extensions/pagetop-bootsier/src/theme/offcanvas/component.rs @@ -1,9 +1,9 @@ use pagetop::prelude::*; -use crate::theme::*; +use crate::prelude::*; use crate::LOCALES_BOOTSIER; -/// Componente para crear un **panel lateral deslizante** ([`offcanvas`]). +/// Componente para crear un **panel lateral deslizante** con contenidos adicionales. /// /// Útil para navegación, filtros, formularios o menús contextuales. Incluye las siguientes /// características principales: @@ -19,28 +19,8 @@ use crate::LOCALES_BOOTSIER; /// - Asocia título y controles de accesibilidad a un identificador único y expone atributos /// adecuados para lectores de pantalla y navegación por teclado. /// +/// Ver ejemplo en el módulo [`offcanvas`]. /// Si no contiene elementos, el componente **no se renderiza**. -/// -/// # Ejemplo -/// -/// ```rust -/// use pagetop::prelude::*; -/// use pagetop_bootsier::theme::*; -/// -/// let panel = Offcanvas::new() -/// .with_id("offcanvas_example") -/// .with_title(L10n::n("Offcanvas title")) -/// .with_placement(offcanvas::Placement::End) -/// .with_backdrop(offcanvas::Backdrop::Enabled) -/// .with_body_scroll(offcanvas::BodyScroll::Enabled) -/// .with_visibility(offcanvas::Visibility::Default) -/// .with_child(Dropdown::new() -/// .with_title(L10n::n("Menu")) -/// .with_item(dropdown::Item::label(L10n::n("Label"))) -/// .with_item(dropdown::Item::link_blank(L10n::n("Docs"), |_| "https://docs.rs".into())) -/// .with_item(dropdown::Item::link(L10n::n("Sign out"), |_| "/signout".into())) -/// ); -/// ``` #[derive(AutoDefault, Clone, Debug, Getters)] pub struct Offcanvas { #[getters(skip)] diff --git a/extensions/pagetop-seaorm/Cargo.toml b/extensions/pagetop-seaorm/Cargo.toml deleted file mode 100644 index 66034137..00000000 --- a/extensions/pagetop-seaorm/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "pagetop-seaorm" -version = "0.0.4" -edition = "2021" - -description = """ - Proporciona a PageTop acceso basado en SeaORM a bases de datos relacionales. -""" -categories = ["database", "development-tools", "asynchronous"] -keywords = ["pagetop", "database", "sql", "orm", "ssr"] - -repository.workspace = true -homepage.workspace = true -license.workspace = true -authors.workspace = true - -[features] -mysql = ["sea-orm/sqlx-mysql"] -postgres = ["sea-orm/sqlx-postgres"] -sqlite = ["sea-orm/sqlx-sqlite"] - -[dependencies] -pagetop.workspace = true -serde.workspace = true - -async-trait = "0.1" -futures = "0.3" -url = "2.5" - -[dependencies.sea-orm] -version = "1.1" -features = ["debug-print", "macros", "runtime-async-std-native-tls"] -default-features = false - -[dependencies.sea-schema] -version = "0.16" diff --git a/extensions/pagetop-seaorm/LICENSE-APACHE b/extensions/pagetop-seaorm/LICENSE-APACHE deleted file mode 100644 index 263ddac1..00000000 --- a/extensions/pagetop-seaorm/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2022 Manuel Cillero - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/extensions/pagetop-seaorm/LICENSE-MIT b/extensions/pagetop-seaorm/LICENSE-MIT deleted file mode 100644 index cd8af3d6..00000000 --- a/extensions/pagetop-seaorm/LICENSE-MIT +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Manuel Cillero - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/extensions/pagetop-seaorm/README.md b/extensions/pagetop-seaorm/README.md deleted file mode 100644 index 42738cd0..00000000 --- a/extensions/pagetop-seaorm/README.md +++ /dev/null @@ -1,150 +0,0 @@ -
- -

PageTop SeaORM

- -

Proporciona a PageTop acceso basado en SeaORM a bases de datos relacionales.

- -[![Doc API](https://img.shields.io/docsrs/pagetop-seaorm?label=Doc%20API&style=for-the-badge&logo=Docs.rs)](https://docs.rs/pagetop-seaorm) -[![Crates.io](https://img.shields.io/crates/v/pagetop-seaorm.svg?style=for-the-badge&logo=ipfs)](https://crates.io/crates/pagetop-seaorm) -[![Descargas](https://img.shields.io/crates/d/pagetop-seaorm.svg?label=Descargas&style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-seaorm) -[![Licencia](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?label=Licencia&style=for-the-badge)](https://git.cillero.es/manuelcillero/pagetop/src/branch/main/extensions/pagetop-seaorm#licencia) - -
- -## 🧭 Sobre PageTop - -[PageTop](https://docs.rs/pagetop) es un entorno de desarrollo que reivindica la esencia de la web -clásica para crear soluciones web SSR (*renderizadas en el servidor*) modulares, extensibles y -configurables, basadas en HTML, CSS y JavaScript. - - -## ⚡️ Guía rápida - -**Añade la dependencia** a tu `Cargo.toml` activando el motor de base de datos que necesites: - -```toml -[dependencies] -pagetop-seaorm = { version = "...", features = ["sqlite"] } -``` - -Las *features* disponibles son `mysql`, `postgres` y `sqlite`. - -**Configura la conexión** en el archivo de configuración de la aplicación: - -```toml -[database] -db_type = "sqlite" -db_name = "my_app.db" -max_pool_size = 5 -``` - -Para MySQL o PostgreSQL añade también `db_user`, `db_pass` y `db_host`. El campo `db_port` es -opcional; si se omite se usa el puerto predeterminado del motor. - -**Declara la extensión** en tu aplicación o en la extensión que la requiera: - -```rust,ignore -use pagetop::prelude::*; - -struct MyApp; - -impl Extension for MyApp { - fn dependencies(&self) -> Vec { - vec![ - &pagetop_seaorm::SeaORM, - ] - } - - fn initialize(&self) { - install_migrations!(m20240101_000001_create_users_table); - } -} - -#[pagetop::main] -async fn main() -> std::io::Result<()> { - Application::prepare(&MyApp).run()?.await -} -``` - -**Escribe las migraciones** usando la API de SeaORM: - -```rust,no_run -use pagetop_seaorm::migration::*; - -pub struct Migration; - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - table_auto(Users::Table) - .col(pk_auto(Users::Id)) - .col(string_uniq(Users::Email)) - .to_owned(), - ) - .await - } -} - -#[derive(DeriveIden)] -enum Users { - Table, - Id, - Email, -} -``` - - -## 📚 Créditos - -Este *crate* se apoya en bibliotecas del ecosistema [SeaQL](https://github.com/SeaQL) como: - -* [SeaORM](https://www.sea-ql.org/SeaORM), ORM asíncrono que usa internamente - [SQLx](https://github.com/launchbadge/sqlx) para el acceso y la ejecución de consultas a la base - de datos. - -* [SeaQuery](https://github.com/SeaQL/sea-query), generador de consultas SQL sobre el que se - construye el motor de migraciones y los *helpers* de esquema. - -* [sea-schema](https://github.com/SeaQL/sea-schema), librería de introspección de esquemas SQL, - usada por el módulo de migraciones para interrogar la estructura real de la base de datos (tablas, - columnas, índices y claves externas). - -El módulo de migraciones (`src/migration/`) incorpora una adaptación de -[sea-orm-migration](https://crates.io/crates/sea-orm-migration). El código que se integra procede de -la versión [**1.1.20**](https://github.com/SeaQL/sea-orm/tree/1.1.20/sea-orm-migration) en lugar de -usarlo como dependencia ya que su paradigma de CLI no es compatible con el ciclo de vida de las -extensiones de PageTop, donde las migraciones deben ejecutarse durante la inicialización de cada -extensión. Los ficheros adaptados del original son: - -| Archivos | Observaciones | -|-----------------------|--------------------------------------------------------------------------| -| `lib.rs` | Incluido en `migration.rs`, descarta módulos y exportaciones del CLI | -| `connection.rs` | Integración completa | -| `manager.rs` | Adapta *features* propias | -| `migrator.rs` | Adapta *features* propias y omite gestión de errores del CLI | -| `prelude.rs` | Absorbido en `migration.rs`, descarta exportaciones del CLI | -| `schema.rs` | Integra con ajustes, original de [loco](https://github.com/loco-rs/loco) | -| `seaql_migrations.rs` | Integración completa | - - -## 🚧 Advertencia - -**PageTop** es un proyecto personal para aprender [Rust](https://www.rust-lang.org/es) y conocer su -ecosistema. Su API está sujeta a cambios frecuentes. No se recomienda su uso en producción, al menos -hasta que se libere la versión **1.0.0**. - - -## 📜 Licencia - -El código está disponible bajo una doble licencia: - - * **Licencia MIT** - ([LICENSE-MIT](LICENSE-MIT) o también https://opensource.org/licenses/MIT) - - * **Licencia Apache, Versión 2.0** - ([LICENSE-APACHE](LICENSE-APACHE) o también https://www.apache.org/licenses/LICENSE-2.0) - -Puedes elegir la licencia que prefieras. Este enfoque de doble licencia es el estándar de facto en -el ecosistema Rust. diff --git a/extensions/pagetop-seaorm/src/config.rs b/extensions/pagetop-seaorm/src/config.rs deleted file mode 100644 index b1276c50..00000000 --- a/extensions/pagetop-seaorm/src/config.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! Opciones de configuración de la extensión. -//! -//! Ejemplo: -//! -//! ```toml -//! [database] -//! db_type = "mysql" -//! db_name = "db" -//! db_user = "user" -//! db_pass = "password" -//! db_host = "localhost" -//! db_port = 3306 -//! max_pool_size = 5 -//! ``` -//! -//! Uso: -//! -//! ```rust -//! # use pagetop_seaorm::config; -//! assert_eq!(config::SETTINGS.database.db_host, "localhost"); -//! ``` -//! -//! Consulta [`pagetop::config`] para ver cómo PageTop lee los archivos de configuración y aplica -//! los valores a los ajustes. - -use pagetop::prelude::*; - -use serde::Deserialize; - -include_config!(SETTINGS: Settings => [ - // [database] - "database.db_type" => "", - "database.db_name" => "", - "database.db_user" => "", - "database.db_pass" => "", - "database.db_host" => "localhost", - "database.max_pool_size" => 5, -]); - -#[derive(Debug, Deserialize)] -/// Tipos para la sección [`[database]`](Database) de [`SETTINGS`]. -pub struct Settings { - pub database: Database, -} - -#[derive(Debug, Deserialize)] -/// Sección `[database]` de la configuración. Forma parte de [`Settings`]. -pub struct Database { - /// Tipo de base de datos: *"mysql"*, *"postgres"* ó *"sqlite"*. - pub db_type: String, - /// Nombre (para mysql/postgres) o referencia (para sqlite) de la base de datos. - pub db_name: String, - /// Usuario de conexión a la base de datos (para mysql/postgres). - pub db_user: String, - /// Contraseña para la conexión a la base de datos (para mysql/postgres). - pub db_pass: String, - /// Servidor de conexión a la base de datos (para mysql/postgres). - pub db_host: String, - /// Puerto de conexión a la base de datos (para mysql/postgres). Si es `None` se usa el puerto - /// predeterminado para el motor: 3306 para MySQL y 5432 para PostgreSQL. - pub db_port: Option, - /// Número máximo de conexiones habilitadas. - pub max_pool_size: u32, -} diff --git a/extensions/pagetop-seaorm/src/db.rs b/extensions/pagetop-seaorm/src/db.rs deleted file mode 100644 index 2b47c399..00000000 --- a/extensions/pagetop-seaorm/src/db.rs +++ /dev/null @@ -1,140 +0,0 @@ -//! API completa de SeaORM para operaciones con la base de datos. -//! -//! Re-exporta el *prelude* de SeaORM (entidades, traits, tipos de valor, macros de derivación…) -//! y expone tres funciones de consulta propias. Con una sola importación tienes todo lo necesario -//! para definir entidades y realizar operaciones CRUD: -//! -//! ```rust,ignore -//! use pagetop_seaorm::db::*; -//! ``` -//! -//! Para definir el esquema de la base de datos o escribir migraciones usa además -//! [`crate::migration`]. - -pub use sea_orm::prelude::*; - -use sea_orm::sea_query::{ - MysqlQueryBuilder, PostgresQueryBuilder, QueryStatementWriter, SqliteQueryBuilder, -}; -use sea_orm::{DatabaseBackend, ExecResult, Statement}; - -/// Devuelve una referencia al pool de conexiones para usarla con el sistema de entidades. -/// -/// Permite pasar la conexión a los métodos `all`, `one`, `exec`, etc. del sistema de entidades -/// de SeaORM. El coste de esta llamada es prácticamente nulo: sólo devuelve una referencia a un -/// valor inicializado una sola vez al arrancar la aplicación. -/// -/// ```rust,no_run -/// use pagetop_seaorm::db::*; -/// -/// // Consultas tipadas con el sistema de entidades de SeaORM: -/// // let users = User::find().all(connection()).await?; -/// // let user = User::find_by_id(1).one(connection()).await?; -/// // User::insert(model).exec(connection()).await?; -/// let _conn = connection(); -/// ``` -pub fn connection() -> &'static DatabaseConnection { - &super::DBCONN -} - -/// Ejecuta una consulta para devolver todas las filas resultantes. -/// -/// Acepta cualquier tipo que implemente [`crate::migration::QueryStatementWriter`] (p. ej. [`crate::migration::SelectStatement`]) y -/// serializa la sentencia al dialecto de la base de datos configurada antes de ejecutarla. Cada -/// fila se devuelve como un [`QueryResult`] sin tipar; extrae los valores con -/// [`QueryResult::try_get`]. -/// -/// ```rust,no_run -/// use pagetop_seaorm::db::*; -/// use pagetop_seaorm::migration::*; -/// -/// async fn example() -> Result<(), DbErr> { -/// let mut stmt = Query::select() -/// .column(Asterisk) -/// .from(Alias::new("users")) -/// .to_owned(); -/// let rows = fetch_all(&mut stmt).await?; -/// for row in rows { -/// let name: String = row.try_get("", "name")?; -/// println!("{name}"); -/// } -/// Ok(()) -/// } -/// ``` -pub async fn fetch_all(stmt: &mut Q) -> Result, DbErr> { - let dbconn = &*super::DBCONN; - let dbbackend = dbconn.get_database_backend(); - dbconn - .query_all(Statement::from_string( - dbbackend, - match dbbackend { - DatabaseBackend::MySql => stmt.to_string(MysqlQueryBuilder), - DatabaseBackend::Postgres => stmt.to_string(PostgresQueryBuilder), - DatabaseBackend::Sqlite => stmt.to_string(SqliteQueryBuilder), - }, - )) - .await -} - -/// Ejecuta una consulta y devuelve sólo la primera fila, si existe. -/// -/// Funciona igual que [`fetch_all`] pero detiene la ejecución tras la primera fila y devuelve -/// `None` si la consulta no produce resultados. -/// -/// ```rust,no_run -/// use pagetop_seaorm::db::*; -/// use pagetop_seaorm::migration::*; -/// -/// async fn example() -> Result<(), DbErr> { -/// let mut stmt = Query::select() -/// .column(Asterisk) -/// .from(Alias::new("users")) -/// .and_where(Expr::col(Alias::new("id")).eq(1)) -/// .to_owned(); -/// if let Some(row) = fetch_one(&mut stmt).await? { -/// let name: String = row.try_get("", "name")?; -/// println!("{name}"); -/// } -/// Ok(()) -/// } -/// ``` -pub async fn fetch_one( - stmt: &mut Q, -) -> Result, DbErr> { - let dbconn = &*super::DBCONN; - let dbbackend = dbconn.get_database_backend(); - dbconn - .query_one(Statement::from_string( - dbbackend, - match dbbackend { - DatabaseBackend::MySql => stmt.to_string(MysqlQueryBuilder), - DatabaseBackend::Postgres => stmt.to_string(PostgresQueryBuilder), - DatabaseBackend::Sqlite => stmt.to_string(SqliteQueryBuilder), - }, - )) - .await -} - -/// Ejecuta una sentencia SQL en crudo (INSERT, UPDATE, DELETE…) y devuelve el resultado de -/// la operación. -/// -/// A diferencia de [`fetch_all`] y [`fetch_one`], no construye la consulta, sino que la recibe -/// como cadena ya formada. Útil para sentencias avanzadas o para migraciones puntuales. El -/// [`ExecResult`] devuelto permite consultar las filas afectadas o el último ID insertado. -/// -/// ```rust,no_run -/// use pagetop_seaorm::db::*; -/// -/// async fn example() -> Result<(), DbErr> { -/// let result = execute("DELETE FROM sessions WHERE expired = 1").await?; -/// println!("Filas eliminadas: {}", result.rows_affected()); -/// Ok(()) -/// } -/// ``` -pub async fn execute(stmt: impl Into) -> Result { - let dbconn = &*super::DBCONN; - let dbbackend = dbconn.get_database_backend(); - dbconn - .execute(Statement::from_string(dbbackend, stmt.into())) - .await -} diff --git a/extensions/pagetop-seaorm/src/lib.rs b/extensions/pagetop-seaorm/src/lib.rs deleted file mode 100644 index 8af917ab..00000000 --- a/extensions/pagetop-seaorm/src/lib.rs +++ /dev/null @@ -1,190 +0,0 @@ -/*! -
- -

PageTop SeaORM

- -

Proporciona a PageTop acceso basado en SeaORM a bases de datos relacionales.

- -[![Doc API](https://img.shields.io/docsrs/pagetop-seaorm?label=Doc%20API&style=for-the-badge&logo=Docs.rs)](https://docs.rs/pagetop-seaorm) -[![Crates.io](https://img.shields.io/crates/v/pagetop-seaorm.svg?style=for-the-badge&logo=ipfs)](https://crates.io/crates/pagetop-seaorm) -[![Descargas](https://img.shields.io/crates/d/pagetop-seaorm.svg?label=Descargas&style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-seaorm) -[![Licencia](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?label=Licencia&style=for-the-badge)](https://git.cillero.es/manuelcillero/pagetop/src/branch/main/extensions/pagetop-seaorm#licencia) - -
- -## 🧭 Sobre PageTop - -[PageTop](https://docs.rs/pagetop) es un entorno de desarrollo que reivindica la esencia de la web -clásica para crear soluciones web SSR (*renderizadas en el servidor*) modulares, extensibles y -configurables, basadas en HTML, CSS y JavaScript. - - -## ⚡️ Guía rápida - -**Añade la dependencia** a tu `Cargo.toml` activando el motor de base de datos que necesites: - -```toml -[dependencies] -pagetop-seaorm = { version = "...", features = ["sqlite"] } -``` - -Las *features* disponibles son `mysql`, `postgres` y `sqlite`. - -**Configura la conexión** en el archivo de configuración de la aplicación: - -```toml -[database] -db_type = "sqlite" -db_name = "my_app.db" -max_pool_size = 5 -``` - -Para MySQL o PostgreSQL añade también `db_user`, `db_pass` y `db_host`. El campo `db_port` es -opcional; si se omite se usa el puerto predeterminado del motor. - -**Declara la extensión** en tu aplicación o en la extensión que la requiera: - -```rust,ignore -use pagetop::prelude::*; - -struct MyApp; - -impl Extension for MyApp { - fn dependencies(&self) -> Vec { - vec![ - &pagetop_seaorm::SeaORM, - ] - } - - fn initialize(&self) { - install_migrations!(m20240101_000001_create_users_table); - } -} - -#[pagetop::main] -async fn main() -> std::io::Result<()> { - Application::prepare(&MyApp).run()?.await -} -``` - -**Escribe las migraciones** usando la API de SeaORM: - -```rust,no_run -use pagetop_seaorm::migration::*; - -pub struct Migration; - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - table_auto(Users::Table) - .col(pk_auto(Users::Id)) - .col(string_uniq(Users::Email)) - .to_owned(), - ) - .await - } -} - -#[derive(DeriveIden)] -enum Users { - Table, - Id, - Email, -} -``` -*/ - -#![doc( - html_favicon_url = "https://git.cillero.es/manuelcillero/pagetop/raw/branch/main/static/favicon.ico" -)] - -use pagetop::prelude::*; - -use sea_orm::{ConnectOptions, Database, DatabaseConnection}; -use url::Url; - -use std::sync::LazyLock; - -include_locales!(LOCALES_SEAORM); - -pub mod config; - -pub mod db; - -pub mod migration; - -pub(crate) use futures::executor::block_on as run_now; - -pub(crate) static DBCONN: LazyLock = LazyLock::new(|| { - trace::info!( - "Connecting to database \"{}\" using a pool of {} connections", - &config::SETTINGS.database.db_name, - &config::SETTINGS.database.max_pool_size - ); - - let db_uri = match config::SETTINGS.database.db_type.as_str() { - "mysql" | "postgres" => { - let mut tmp_uri = Url::parse( - format!( - "{}://{}/{}", - &config::SETTINGS.database.db_type, - &config::SETTINGS.database.db_host, - &config::SETTINGS.database.db_name - ) - .as_str(), - ) - .unwrap(); - tmp_uri - .set_username(config::SETTINGS.database.db_user.as_str()) - .unwrap(); - // https://github.com/launchbadge/sqlx/issues/1624 - tmp_uri - .set_password(Some(config::SETTINGS.database.db_pass.as_str())) - .unwrap(); - if let Some(port) = config::SETTINGS.database.db_port { - tmp_uri.set_port(Some(port)).unwrap(); - } - tmp_uri - } - "sqlite" => Url::parse( - format!( - "{}://{}", - &config::SETTINGS.database.db_type, - &config::SETTINGS.database.db_name - ) - .as_str(), - ) - .unwrap(), - _ => panic!( - "Unrecognized database type \"{}\"", - config::SETTINGS.database.db_type - ), - }; - - run_now(Database::connect::({ - let mut db_opt = ConnectOptions::new(db_uri.to_string()); - db_opt.max_connections(config::SETTINGS.database.max_pool_size); - db_opt - })) - .unwrap_or_else(|_| panic!("Failed to connect to database")) -}); - -/// Implementa la extensión. -pub struct SeaORM; - -impl Extension for SeaORM { - fn name(&self) -> L10n { - L10n::t("extension_name", &LOCALES_SEAORM) - } - - fn description(&self) -> L10n { - L10n::t("extension_description", &LOCALES_SEAORM) - } - - fn initialize(&self) { - std::sync::LazyLock::force(&DBCONN); - } -} diff --git a/extensions/pagetop-seaorm/src/locale/en-US/extension.ftl b/extensions/pagetop-seaorm/src/locale/en-US/extension.ftl deleted file mode 100644 index f80d7aa4..00000000 --- a/extensions/pagetop-seaorm/src/locale/en-US/extension.ftl +++ /dev/null @@ -1,2 +0,0 @@ -extension_name = SeaORM support -extension_description = Provides SeaORM-based access to relational databases. diff --git a/extensions/pagetop-seaorm/src/locale/es-ES/extension.ftl b/extensions/pagetop-seaorm/src/locale/es-ES/extension.ftl deleted file mode 100644 index e48e4653..00000000 --- a/extensions/pagetop-seaorm/src/locale/es-ES/extension.ftl +++ /dev/null @@ -1,2 +0,0 @@ -extension_name = Soporte a SeaORM -extension_description = Proporciona acceso basado en SeaORM a bases de datos relacionales. diff --git a/extensions/pagetop-seaorm/src/migration.rs b/extensions/pagetop-seaorm/src/migration.rs deleted file mode 100644 index 14b8f85b..00000000 --- a/extensions/pagetop-seaorm/src/migration.rs +++ /dev/null @@ -1,156 +0,0 @@ -//! API para definir y ejecutar migraciones de base de datos. -//! -//! Re-exporta los tipos de SeaORM necesarios para escribir migraciones y ofrece las macros -//! [`crate::install_migrations`] y [`crate::uninstall_migrations`] para aplicarlas o revertirlas al -//! arrancar la extensión. -//! -//! ```rust,ignore -//! use pagetop_seaorm::db::*; -//! use pagetop_seaorm::migration::*; -//! ``` - -// **< Adaptación de `sea-orm-migration` (ver §Créditos en README.md) >***************************** - -//pub mod cli; -pub mod connection; -pub mod manager; -pub mod migrator; -//pub mod prelude; -pub mod schema; -pub mod seaql_migrations; -//pub mod util; - -pub use connection::*; -pub use manager::*; -//pub use migrator::*; - -pub use async_trait; -//pub use sea_orm; -//pub use sea_orm::sea_query; -pub use sea_orm::DbErr; - -pub trait MigrationName { - fn name(&self) -> &str; -} - -/// The migration definition -#[async_trait::async_trait] -pub trait MigrationTrait: MigrationName + Send + Sync { - /// Define actions to perform when applying the migration - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr>; - - /// Define actions to perform when rolling back the migration - async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> { - Err(DbErr::Migration( - "Rollback not implemented for this migration".to_owned(), - )) - } -} - -// ************************************************************************************************* - -pub use migrator::MigratorTrait; -pub use schema::*; -pub use sea_orm::sea_query::*; -pub use sea_orm::DeriveIden; - -use pagetop::core::TypeInfo; -use pagetop::trace; - -impl MigrationName for M { - fn name(&self) -> &str { - TypeInfo::NameTo(-2).of::() - } -} - -pub type MigrationItem = Box; - -pub trait MigratorBase { - fn run_up(); - - fn run_down(); -} - -#[rustfmt::skip] -impl MigratorBase for M { - fn run_up() { - if let Err(e) = super::run_now(Self::up(SchemaManagerConnection::Connection(&super::DBCONN), None)) { - trace::error!("Migration upgrade failed ({})", e); - }; - } - - fn run_down() { - if let Err(e) = super::run_now(Self::down(SchemaManagerConnection::Connection(&super::DBCONN), None)) { - trace::error!("Migration downgrade failed ({})", e); - }; - } -} - -/// Aplica las migraciones pendientes al arrancar una extensión. -/// -/// Recibe uno o más módulos de migración y ejecuta el método `up` de los que aún no estén -/// registrados en la tabla `seaql_migrations`. Se invoca habitualmente desde -/// [`Extension::initialize`](pagetop::core::extension::Extension::initialize). -/// -/// ```rust,ignore -/// impl Extension for MyExt { -/// fn initialize(&self) { -/// install_migrations!( -/// m20240101_000001_create_users_table, -/// m20240115_000002_add_email_index, -/// ); -/// } -/// } -/// ``` -#[macro_export] -macro_rules! install_migrations { - ( $($migration_module:ident),+ $(,)? ) => {{ - use $crate::migration::{MigrationItem, MigratorBase, MigratorTrait}; - - struct Migrator; - impl MigratorTrait for Migrator { - fn migrations() -> Vec { - let mut m = Vec::::new(); - $( - m.push(Box::new(migration::$migration_module::Migration)); - )* - m - } - } - Migrator::run_up(); - }}; -} - -/// Revierte las migraciones de una extensión en orden inverso al de su aplicación. -/// -/// Ejecuta el método `down` de cada migración indicada. Si alguna no implementa `down`, -/// detiene el proceso con un error. Complementario a [`crate::install_migrations`]. -/// -/// ```rust,ignore -/// impl Extension for MyExt { -/// fn uninitialize(&self) { -/// uninstall_migrations!( -/// m20240101_000001_create_users_table, -/// m20240115_000002_add_email_index, -/// ); -/// } -/// } -/// ``` -#[macro_export] -macro_rules! uninstall_migrations { - ( $($migration_module:ident),+ $(,)? ) => {{ - use $crate::migration::{MigrationItem, MigratorBase, MigratorTrait}; - - struct Migrator; - impl MigratorTrait for Migrator { - fn migrations() -> Vec { - let mut m = Vec::::new(); - $( - m.push(Box::new(migration::$migration_module::Migration)); - )* - m - } - } - Migrator::run_down(); - }}; -} diff --git a/extensions/pagetop-seaorm/src/migration/connection.rs b/extensions/pagetop-seaorm/src/migration/connection.rs deleted file mode 100644 index 7c937a37..00000000 --- a/extensions/pagetop-seaorm/src/migration/connection.rs +++ /dev/null @@ -1,148 +0,0 @@ -use futures::Future; -use sea_orm::{ - AccessMode, ConnectionTrait, DatabaseConnection, DatabaseTransaction, DbBackend, DbErr, - ExecResult, IsolationLevel, QueryResult, Statement, TransactionError, TransactionTrait, -}; -use std::pin::Pin; - -pub enum SchemaManagerConnection<'c> { - Connection(&'c DatabaseConnection), - Transaction(&'c DatabaseTransaction), -} - -#[async_trait::async_trait] -impl ConnectionTrait for SchemaManagerConnection<'_> { - fn get_database_backend(&self) -> DbBackend { - match self { - SchemaManagerConnection::Connection(conn) => conn.get_database_backend(), - SchemaManagerConnection::Transaction(trans) => trans.get_database_backend(), - } - } - - async fn execute(&self, stmt: Statement) -> Result { - match self { - SchemaManagerConnection::Connection(conn) => conn.execute(stmt).await, - SchemaManagerConnection::Transaction(trans) => trans.execute(stmt).await, - } - } - - async fn execute_unprepared(&self, sql: &str) -> Result { - match self { - SchemaManagerConnection::Connection(conn) => conn.execute_unprepared(sql).await, - SchemaManagerConnection::Transaction(trans) => trans.execute_unprepared(sql).await, - } - } - - async fn query_one(&self, stmt: Statement) -> Result, DbErr> { - match self { - SchemaManagerConnection::Connection(conn) => conn.query_one(stmt).await, - SchemaManagerConnection::Transaction(trans) => trans.query_one(stmt).await, - } - } - - async fn query_all(&self, stmt: Statement) -> Result, DbErr> { - match self { - SchemaManagerConnection::Connection(conn) => conn.query_all(stmt).await, - SchemaManagerConnection::Transaction(trans) => trans.query_all(stmt).await, - } - } - - fn is_mock_connection(&self) -> bool { - match self { - SchemaManagerConnection::Connection(conn) => conn.is_mock_connection(), - SchemaManagerConnection::Transaction(trans) => trans.is_mock_connection(), - } - } -} - -#[async_trait::async_trait] -impl TransactionTrait for SchemaManagerConnection<'_> { - async fn begin(&self) -> Result { - match self { - SchemaManagerConnection::Connection(conn) => conn.begin().await, - SchemaManagerConnection::Transaction(trans) => trans.begin().await, - } - } - - async fn begin_with_config( - &self, - isolation_level: Option, - access_mode: Option, - ) -> Result { - match self { - SchemaManagerConnection::Connection(conn) => { - conn.begin_with_config(isolation_level, access_mode).await - } - SchemaManagerConnection::Transaction(trans) => { - trans.begin_with_config(isolation_level, access_mode).await - } - } - } - - async fn transaction(&self, callback: F) -> Result> - where - F: for<'a> FnOnce( - &'a DatabaseTransaction, - ) -> Pin> + Send + 'a>> - + Send, - T: Send, - E: std::fmt::Display + std::fmt::Debug + Send, - { - match self { - SchemaManagerConnection::Connection(conn) => conn.transaction(callback).await, - SchemaManagerConnection::Transaction(trans) => trans.transaction(callback).await, - } - } - - async fn transaction_with_config( - &self, - callback: F, - isolation_level: Option, - access_mode: Option, - ) -> Result> - where - F: for<'a> FnOnce( - &'a DatabaseTransaction, - ) -> Pin> + Send + 'a>> - + Send, - T: Send, - E: std::fmt::Display + std::fmt::Debug + Send, - { - match self { - SchemaManagerConnection::Connection(conn) => { - conn.transaction_with_config(callback, isolation_level, access_mode) - .await - } - SchemaManagerConnection::Transaction(trans) => { - trans - .transaction_with_config(callback, isolation_level, access_mode) - .await - } - } - } -} - -pub trait IntoSchemaManagerConnection<'c>: Send -where - Self: 'c, -{ - fn into_schema_manager_connection(self) -> SchemaManagerConnection<'c>; -} - -impl<'c> IntoSchemaManagerConnection<'c> for SchemaManagerConnection<'c> { - fn into_schema_manager_connection(self) -> SchemaManagerConnection<'c> { - self - } -} - -impl<'c> IntoSchemaManagerConnection<'c> for &'c DatabaseConnection { - fn into_schema_manager_connection(self) -> SchemaManagerConnection<'c> { - SchemaManagerConnection::Connection(self) - } -} - -impl<'c> IntoSchemaManagerConnection<'c> for &'c DatabaseTransaction { - fn into_schema_manager_connection(self) -> SchemaManagerConnection<'c> { - SchemaManagerConnection::Transaction(self) - } -} diff --git a/extensions/pagetop-seaorm/src/migration/manager.rs b/extensions/pagetop-seaorm/src/migration/manager.rs deleted file mode 100644 index 3f962bdf..00000000 --- a/extensions/pagetop-seaorm/src/migration/manager.rs +++ /dev/null @@ -1,186 +0,0 @@ -use super::{IntoSchemaManagerConnection, SchemaManagerConnection}; -use sea_orm::sea_query::{ - extension::postgres::{TypeAlterStatement, TypeCreateStatement, TypeDropStatement}, - ForeignKeyCreateStatement, ForeignKeyDropStatement, IndexCreateStatement, IndexDropStatement, - SelectStatement, TableAlterStatement, TableCreateStatement, TableDropStatement, - TableRenameStatement, TableTruncateStatement, -}; -use sea_orm::{ConnectionTrait, DbBackend, DbErr, StatementBuilder}; -#[allow(unused_imports)] -use sea_schema::probe::SchemaProbe; - -/// Helper struct for writing migration scripts in migration file -pub struct SchemaManager<'c> { - conn: SchemaManagerConnection<'c>, -} - -impl<'c> SchemaManager<'c> { - pub fn new(conn: T) -> Self - where - T: IntoSchemaManagerConnection<'c>, - { - Self { - conn: conn.into_schema_manager_connection(), - } - } - - pub async fn exec_stmt(&self, stmt: S) -> Result<(), DbErr> - where - S: StatementBuilder, - { - let builder = self.conn.get_database_backend(); - self.conn.execute(builder.build(&stmt)).await.map(|_| ()) - } - - pub fn get_database_backend(&self) -> DbBackend { - self.conn.get_database_backend() - } - - pub fn get_connection(&self) -> &SchemaManagerConnection<'c> { - &self.conn - } -} - -/// Schema Creation -impl SchemaManager<'_> { - pub async fn create_table(&self, stmt: TableCreateStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } - - pub async fn create_index(&self, stmt: IndexCreateStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } - - pub async fn create_foreign_key(&self, stmt: ForeignKeyCreateStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } - - pub async fn create_type(&self, stmt: TypeCreateStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } -} - -/// Schema Mutation -impl SchemaManager<'_> { - pub async fn alter_table(&self, stmt: TableAlterStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } - - pub async fn drop_table(&self, stmt: TableDropStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } - - pub async fn rename_table(&self, stmt: TableRenameStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } - - pub async fn truncate_table(&self, stmt: TableTruncateStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } - - pub async fn drop_index(&self, stmt: IndexDropStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } - - pub async fn drop_foreign_key(&self, stmt: ForeignKeyDropStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } - - pub async fn alter_type(&self, stmt: TypeAlterStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } - - pub async fn drop_type(&self, stmt: TypeDropStatement) -> Result<(), DbErr> { - self.exec_stmt(stmt).await - } -} - -/// Schema Inspection. -impl SchemaManager<'_> { - pub async fn has_table(&self, table: T) -> Result - where - T: AsRef, - { - has_table(&self.conn, table).await - } - - pub async fn has_column(&self, _table: T, _column: C) -> Result - where - T: AsRef, - C: AsRef, - { - let _stmt: SelectStatement = match self.conn.get_database_backend() { - #[cfg(feature = "mysql")] - DbBackend::MySql => sea_schema::mysql::MySql.has_column(_table, _column), - #[cfg(feature = "postgres")] - DbBackend::Postgres => sea_schema::postgres::Postgres.has_column(_table, _column), - #[cfg(feature = "sqlite")] - DbBackend::Sqlite => sea_schema::sqlite::Sqlite.has_column(_table, _column), - #[allow(unreachable_patterns)] - other => panic!("{other:?} feature is off"), - }; - - #[allow(unreachable_code)] - let builder = self.conn.get_database_backend(); - let res = self - .conn - .query_one(builder.build(&_stmt)) - .await? - .ok_or_else(|| DbErr::Custom("Failed to check column exists".to_owned()))?; - - res.try_get("", "has_column") - } - - pub async fn has_index(&self, _table: T, _index: I) -> Result - where - T: AsRef, - I: AsRef, - { - let _stmt: SelectStatement = match self.conn.get_database_backend() { - #[cfg(feature = "mysql")] - DbBackend::MySql => sea_schema::mysql::MySql.has_index(_table, _index), - #[cfg(feature = "postgres")] - DbBackend::Postgres => sea_schema::postgres::Postgres.has_index(_table, _index), - #[cfg(feature = "sqlite")] - DbBackend::Sqlite => sea_schema::sqlite::Sqlite.has_index(_table, _index), - #[allow(unreachable_patterns)] - other => panic!("{other:?} feature is off"), - }; - - #[allow(unreachable_code)] - let builder = self.conn.get_database_backend(); - let res = self - .conn - .query_one(builder.build(&_stmt)) - .await? - .ok_or_else(|| DbErr::Custom("Failed to check index exists".to_owned()))?; - - res.try_get("", "has_index") - } -} - -pub(crate) async fn has_table(conn: &C, _table: T) -> Result -where - C: ConnectionTrait, - T: AsRef, -{ - let _stmt: SelectStatement = match conn.get_database_backend() { - #[cfg(feature = "mysql")] - DbBackend::MySql => sea_schema::mysql::MySql.has_table(_table), - #[cfg(feature = "postgres")] - DbBackend::Postgres => sea_schema::postgres::Postgres.has_table(_table), - #[cfg(feature = "sqlite")] - DbBackend::Sqlite => sea_schema::sqlite::Sqlite.has_table(_table), - #[allow(unreachable_patterns)] - other => panic!("{other:?} feature is off"), - }; - - #[allow(unreachable_code)] - let builder = conn.get_database_backend(); - let res = conn - .query_one(builder.build(&_stmt)) - .await? - .ok_or_else(|| DbErr::Custom("Failed to check table exists".to_owned()))?; - - res.try_get("", "has_table") -} diff --git a/extensions/pagetop-seaorm/src/migration/migrator.rs b/extensions/pagetop-seaorm/src/migration/migrator.rs deleted file mode 100644 index 45ecdbac..00000000 --- a/extensions/pagetop-seaorm/src/migration/migrator.rs +++ /dev/null @@ -1,617 +0,0 @@ -use futures::Future; -use std::collections::HashSet; -use std::fmt::Display; -use std::pin::Pin; -use std::time::SystemTime; - -use pagetop::trace::info; - -use sea_orm::sea_query::{ - self, extension::postgres::Type, Alias, Expr, ExprTrait, ForeignKey, IntoIden, Order, Query, - SelectStatement, SimpleExpr, Table, -}; -use sea_orm::{ - ActiveModelTrait, ActiveValue, Condition, ConnectionTrait, DbBackend, DbErr, DeriveIden, - DynIden, EntityTrait, FromQueryResult, Iterable, QueryFilter, Schema, Statement, - TransactionTrait, -}; -#[allow(unused_imports)] -use sea_schema::probe::SchemaProbe; - -use super::{seaql_migrations, IntoSchemaManagerConnection, MigrationTrait, SchemaManager}; - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -/// Status of migration -pub enum MigrationStatus { - /// Not yet applied - Pending, - /// Applied - Applied, -} - -impl Display for MigrationStatus { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let status = match self { - MigrationStatus::Pending => "Pending", - MigrationStatus::Applied => "Applied", - }; - write!(f, "{status}") - } -} - -pub struct Migration { - migration: Box, - status: MigrationStatus, -} - -impl Migration { - /// Get migration name from MigrationName trait implementation - pub fn name(&self) -> &str { - self.migration.name() - } - - /// Get migration status - pub fn status(&self) -> MigrationStatus { - self.status - } -} - -/// Performing migrations on a database -#[async_trait::async_trait] -pub trait MigratorTrait: Send { - /// Vector of migrations in time sequence - fn migrations() -> Vec>; - - /// Name of the migration table, it is `seaql_migrations` by default - fn migration_table_name() -> DynIden { - seaql_migrations::Entity.into_iden() - } - - /// Get list of migrations wrapped in `Migration` struct - fn get_migration_files() -> Vec { - Self::migrations() - .into_iter() - .map(|migration| Migration { - migration, - status: MigrationStatus::Pending, - }) - .collect() - } - - /// Get list of applied migrations from database - async fn get_migration_models(db: &C) -> Result, DbErr> - where - C: ConnectionTrait, - { - Self::install(db).await?; - let stmt = Query::select() - .table_name(Self::migration_table_name()) - .columns(seaql_migrations::Column::iter().map(IntoIden::into_iden)) - .order_by(seaql_migrations::Column::Version, Order::Asc) - .to_owned(); - let builder = db.get_database_backend(); - seaql_migrations::Model::find_by_statement(builder.build(&stmt)) - .all(db) - .await - } - - /// Get list of migrations with status - async fn get_migration_with_status(db: &C) -> Result, DbErr> - where - C: ConnectionTrait, - { - Self::install(db).await?; - let mut migration_files = Self::get_migration_files(); - let migration_models = Self::get_migration_models(db).await?; - - let migration_in_db: HashSet = migration_models - .into_iter() - .map(|model| model.version) - .collect(); - let migration_in_fs: HashSet = migration_files - .iter() - .map(|file| file.migration.name().to_string()) - .collect(); - - let pending_migrations = &migration_in_fs - &migration_in_db; - for migration_file in migration_files.iter_mut() { - if !pending_migrations.contains(migration_file.migration.name()) { - migration_file.status = MigrationStatus::Applied; - } - } - /* - let missing_migrations_in_fs = &migration_in_db - &migration_in_fs; - let errors: Vec = missing_migrations_in_fs - .iter() - .map(|missing_migration| { - format!("Migration file of version '{missing_migration}' is missing, this migration has been applied but its file is missing") - }).collect(); - - if !errors.is_empty() { - Err(DbErr::Custom(errors.join("\n"))) - } else { */ - Ok(migration_files) - /* } */ - } - - /// Get list of pending migrations - async fn get_pending_migrations(db: &C) -> Result, DbErr> - where - C: ConnectionTrait, - { - Self::install(db).await?; - Ok(Self::get_migration_with_status(db) - .await? - .into_iter() - .filter(|file| file.status == MigrationStatus::Pending) - .collect()) - } - - /// Get list of applied migrations - async fn get_applied_migrations(db: &C) -> Result, DbErr> - where - C: ConnectionTrait, - { - Self::install(db).await?; - Ok(Self::get_migration_with_status(db) - .await? - .into_iter() - .filter(|file| file.status == MigrationStatus::Applied) - .collect()) - } - - /// Create migration table `seaql_migrations` in the database - async fn install(db: &C) -> Result<(), DbErr> - where - C: ConnectionTrait, - { - let builder = db.get_database_backend(); - let table_name = Self::migration_table_name(); - let schema = Schema::new(builder); - let mut stmt = schema - .create_table_from_entity(seaql_migrations::Entity) - .table_name(table_name); - stmt.if_not_exists(); - db.execute(builder.build(&stmt)).await.map(|_| ()) - } - - /// Check the status of all migrations - async fn status(db: &C) -> Result<(), DbErr> - where - C: ConnectionTrait, - { - Self::install(db).await?; - - info!("Checking migration status"); - - for Migration { migration, status } in Self::get_migration_with_status(db).await? { - info!("Migration '{}'... {}", migration.name(), status); - } - - Ok(()) - } - - /// Drop all tables from the database, then reapply all migrations - async fn fresh<'c, C>(db: C) -> Result<(), DbErr> - where - C: IntoSchemaManagerConnection<'c>, - { - exec_with_connection::<'_, _, _>(db, move |manager| { - Box::pin(async move { exec_fresh::(manager).await }) - }) - .await - } - - /// Rollback all applied migrations, then reapply all migrations - async fn refresh<'c, C>(db: C) -> Result<(), DbErr> - where - C: IntoSchemaManagerConnection<'c>, - { - exec_with_connection::<'_, _, _>(db, move |manager| { - Box::pin(async move { - exec_down::(manager, None).await?; - exec_up::(manager, None).await - }) - }) - .await - } - - /// Rollback all applied migrations - async fn reset<'c, C>(db: C) -> Result<(), DbErr> - where - C: IntoSchemaManagerConnection<'c>, - { - exec_with_connection::<'_, _, _>(db, move |manager| { - Box::pin(async move { exec_down::(manager, None).await }) - }) - .await - } - - /// Apply pending migrations - async fn up<'c, C>(db: C, steps: Option) -> Result<(), DbErr> - where - C: IntoSchemaManagerConnection<'c>, - { - exec_with_connection::<'_, _, _>(db, move |manager| { - Box::pin(async move { exec_up::(manager, steps).await }) - }) - .await - } - - /// Rollback applied migrations - async fn down<'c, C>(db: C, steps: Option) -> Result<(), DbErr> - where - C: IntoSchemaManagerConnection<'c>, - { - exec_with_connection::<'_, _, _>(db, move |manager| { - Box::pin(async move { exec_down::(manager, steps).await }) - }) - .await - } -} - -async fn exec_with_connection<'c, C, F>(db: C, f: F) -> Result<(), DbErr> -where - C: IntoSchemaManagerConnection<'c>, - F: for<'b> Fn( - &'b SchemaManager<'_>, - ) -> Pin> + Send + 'b>>, -{ - let db = db.into_schema_manager_connection(); - - match db.get_database_backend() { - DbBackend::Postgres => { - let transaction = db.begin().await?; - let manager = SchemaManager::new(&transaction); - f(&manager).await?; - transaction.commit().await - } - DbBackend::MySql | DbBackend::Sqlite => { - let manager = SchemaManager::new(db); - f(&manager).await - } - } -} - -async fn exec_fresh(manager: &SchemaManager<'_>) -> Result<(), DbErr> -where - M: MigratorTrait + ?Sized, -{ - let db = manager.get_connection(); - - M::install(db).await?; - let db_backend = db.get_database_backend(); - - // Temporarily disable the foreign key check - if db_backend == DbBackend::Sqlite { - info!("Disabling foreign key check"); - db.execute(Statement::from_string( - db_backend, - "PRAGMA foreign_keys = OFF".to_owned(), - )) - .await?; - info!("Foreign key check disabled"); - } - - // Drop all foreign keys - if db_backend == DbBackend::MySql { - info!("Dropping all foreign keys"); - let stmt = query_mysql_foreign_keys(db); - let rows = db.query_all(db_backend.build(&stmt)).await?; - for row in rows.into_iter() { - let constraint_name: String = row.try_get("", "CONSTRAINT_NAME")?; - let table_name: String = row.try_get("", "TABLE_NAME")?; - info!( - "Dropping foreign key '{}' from table '{}'", - constraint_name, table_name - ); - let mut stmt = ForeignKey::drop(); - stmt.table(Alias::new(table_name.as_str())) - .name(constraint_name.as_str()); - db.execute(db_backend.build(&stmt)).await?; - info!("Foreign key '{}' has been dropped", constraint_name); - } - info!("All foreign keys dropped"); - } - - // Drop all tables - let stmt = query_tables(db).await; - let rows = db.query_all(db_backend.build(&stmt)).await?; - for row in rows.into_iter() { - let table_name: String = row.try_get("", "table_name")?; - info!("Dropping table '{}'", table_name); - let mut stmt = Table::drop(); - stmt.table(Alias::new(table_name.as_str())) - .if_exists() - .cascade(); - db.execute(db_backend.build(&stmt)).await?; - info!("Table '{}' has been dropped", table_name); - } - - // Drop all types - if db_backend == DbBackend::Postgres { - info!("Dropping all types"); - let stmt = query_pg_types(db); - let rows = db.query_all(db_backend.build(&stmt)).await?; - for row in rows { - let type_name: String = row.try_get("", "typname")?; - info!("Dropping type '{}'", type_name); - let mut stmt = Type::drop(); - stmt.name(Alias::new(&type_name)); - db.execute(db_backend.build(&stmt)).await?; - info!("Type '{}' has been dropped", type_name); - } - } - - // Restore the foreign key check - if db_backend == DbBackend::Sqlite { - info!("Restoring foreign key check"); - db.execute(Statement::from_string( - db_backend, - "PRAGMA foreign_keys = ON".to_owned(), - )) - .await?; - info!("Foreign key check restored"); - } - - // Reapply all migrations - exec_up::(manager, None).await -} - -async fn exec_up(manager: &SchemaManager<'_>, mut steps: Option) -> Result<(), DbErr> -where - M: MigratorTrait + ?Sized, -{ - let db = manager.get_connection(); - - M::install(db).await?; - /* - if let Some(steps) = steps { - info!("Applying {} pending migrations", steps); - } else { - info!("Applying all pending migrations"); - } - */ - let migrations = M::get_pending_migrations(db).await?.into_iter(); - /* - if migrations.len() == 0 { - info!("No pending migrations"); - } - */ - for Migration { migration, .. } in migrations { - if let Some(steps) = steps.as_mut() { - if steps == &0 { - break; - } - *steps -= 1; - } - info!("Applying migration '{}'", migration.name()); - migration.up(manager).await?; - info!("Migration '{}' has been applied", migration.name()); - let now = SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .expect("SystemTime before UNIX EPOCH!"); - seaql_migrations::Entity::insert(seaql_migrations::ActiveModel { - version: ActiveValue::Set(migration.name().to_owned()), - applied_at: ActiveValue::Set(now.as_secs() as i64), - }) - .table_name(M::migration_table_name()) - .exec(db) - .await?; - } - - Ok(()) -} - -async fn exec_down(manager: &SchemaManager<'_>, mut steps: Option) -> Result<(), DbErr> -where - M: MigratorTrait + ?Sized, -{ - let db = manager.get_connection(); - - M::install(db).await?; - - if let Some(steps) = steps { - info!("Rolling back {} applied migrations", steps); - } else { - info!("Rolling back all applied migrations"); - } - - let migrations = M::get_applied_migrations(db).await?.into_iter().rev(); - if migrations.len() == 0 { - info!("No applied migrations"); - } - for Migration { migration, .. } in migrations { - if let Some(steps) = steps.as_mut() { - if steps == &0 { - break; - } - *steps -= 1; - } - info!("Rolling back migration '{}'", migration.name()); - migration.down(manager).await?; - info!("Migration '{}' has been rollbacked", migration.name()); - seaql_migrations::Entity::delete_many() - .filter(Expr::col(seaql_migrations::Column::Version).eq(migration.name())) - .table_name(M::migration_table_name()) - .exec(db) - .await?; - } - - Ok(()) -} - -async fn query_tables(db: &C) -> SelectStatement -where - C: ConnectionTrait, -{ - match db.get_database_backend() { - #[cfg(feature = "mysql")] - DbBackend::MySql => sea_schema::mysql::MySql.query_tables(), - #[cfg(feature = "postgres")] - DbBackend::Postgres => sea_schema::postgres::Postgres.query_tables(), - #[cfg(feature = "sqlite")] - DbBackend::Sqlite => sea_schema::sqlite::Sqlite.query_tables(), - #[allow(unreachable_patterns)] - other => panic!("{other:?} feature is off"), - } -} - -fn get_current_schema(db: &C) -> SimpleExpr -where - C: ConnectionTrait, -{ - match db.get_database_backend() { - #[cfg(feature = "mysql")] - DbBackend::MySql => sea_schema::mysql::MySql::get_current_schema(), - #[cfg(feature = "postgres")] - DbBackend::Postgres => sea_schema::postgres::Postgres::get_current_schema(), - #[cfg(feature = "sqlite")] - DbBackend::Sqlite => sea_schema::sqlite::Sqlite::get_current_schema(), - #[allow(unreachable_patterns)] - other => panic!("{other:?} feature is off"), - } -} - -#[derive(DeriveIden)] -enum InformationSchema { - #[sea_orm(iden = "information_schema")] - Schema, - #[sea_orm(iden = "TABLE_NAME")] - TableName, - #[sea_orm(iden = "CONSTRAINT_NAME")] - ConstraintName, - TableConstraints, - TableSchema, - ConstraintType, -} - -fn query_mysql_foreign_keys(db: &C) -> SelectStatement -where - C: ConnectionTrait, -{ - let mut stmt = Query::select(); - stmt.columns([ - InformationSchema::TableName, - InformationSchema::ConstraintName, - ]) - .from(( - InformationSchema::Schema, - InformationSchema::TableConstraints, - )) - .cond_where( - Condition::all() - .add(get_current_schema(db).equals(( - InformationSchema::TableConstraints, - InformationSchema::TableSchema, - ))) - .add( - Expr::col(( - InformationSchema::TableConstraints, - InformationSchema::ConstraintType, - )) - .eq("FOREIGN KEY"), - ), - ); - stmt -} - -#[derive(DeriveIden)] -enum PgType { - Table, - Oid, - Typname, - Typnamespace, - Typelem, -} - -#[derive(DeriveIden)] -enum PgDepend { - Table, - Objid, - Deptype, - Refclassid, -} - -#[derive(DeriveIden)] -enum PgNamespace { - Table, - Oid, - Nspname, -} - -fn query_pg_types(db: &C) -> SelectStatement -where - C: ConnectionTrait, -{ - Query::select() - .column(PgType::Typname) - .from(PgType::Table) - .left_join( - PgNamespace::Table, - Expr::col((PgNamespace::Table, PgNamespace::Oid)) - .equals((PgType::Table, PgType::Typnamespace)), - ) - .left_join( - PgDepend::Table, - Expr::col((PgDepend::Table, PgDepend::Objid)) - .equals((PgType::Table, PgType::Oid)) - .and( - Expr::col((PgDepend::Table, PgDepend::Refclassid)) - .eq(Expr::cust("'pg_extension'::regclass::oid")), - ) - .and(Expr::col((PgDepend::Table, PgDepend::Deptype)).eq(Expr::cust("'e'"))), - ) - .and_where(get_current_schema(db).equals((PgNamespace::Table, PgNamespace::Nspname))) - .and_where(Expr::col((PgType::Table, PgType::Typelem)).eq(0)) - .and_where(Expr::col((PgDepend::Table, PgDepend::Objid)).is_null()) - .take() -} - -trait QueryTable { - type Statement; - - fn table_name(self, table_name: DynIden) -> Self::Statement; -} - -impl QueryTable for SelectStatement { - type Statement = SelectStatement; - - fn table_name(mut self, table_name: DynIden) -> SelectStatement { - self.from(table_name); - self - } -} - -impl QueryTable for sea_query::TableCreateStatement { - type Statement = sea_query::TableCreateStatement; - - fn table_name(mut self, table_name: DynIden) -> sea_query::TableCreateStatement { - self.table(table_name); - self - } -} - -impl QueryTable for sea_orm::Insert -where - A: ActiveModelTrait, -{ - type Statement = sea_orm::Insert; - - fn table_name(mut self, table_name: DynIden) -> sea_orm::Insert { - sea_orm::QueryTrait::query(&mut self).into_table(table_name); - self - } -} - -impl QueryTable for sea_orm::DeleteMany -where - E: EntityTrait, -{ - type Statement = sea_orm::DeleteMany; - - fn table_name(mut self, table_name: DynIden) -> sea_orm::DeleteMany { - sea_orm::QueryTrait::query(&mut self).from_table(table_name); - self - } -} diff --git a/extensions/pagetop-seaorm/src/migration/schema.rs b/extensions/pagetop-seaorm/src/migration/schema.rs deleted file mode 100644 index 4dea5ee2..00000000 --- a/extensions/pagetop-seaorm/src/migration/schema.rs +++ /dev/null @@ -1,611 +0,0 @@ -//! Adaptación de -//! -//! # Ayudantes de esquema de base de datos -//! -//! Define funciones y ayudantes para crear esquemas de tablas usando `sea-orm` y `sea-query`. -//! -//! # Ejemplo -//! -//! El siguiente ejemplo muestra cómo escribir un archivo de migración usando los ayudantes -//! de esquema. -//! -//! ```rust -//! use pagetop_seaorm::migration::*; -//! -//! pub struct Migration; -//! -//! #[async_trait::async_trait] -//! impl MigrationTrait for Migration { -//! async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { -//! let table = table_auto(Users::Table) -//! .col(pk_auto(Users::Id)) -//! .col(uuid(Users::Pid)) -//! .col(string_uniq(Users::Email)) -//! .col(string(Users::Password)) -//! .col(string(Users::Name)) -//! .col(string_null(Users::ResetToken)) -//! .col(timestamp_null(Users::ResetSentAt)) -//! .to_owned(); -//! manager.create_table(table).await?; -//! Ok(()) -//! } -//! -//! async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { -//! manager -//! .drop_table(Table::drop().table(Users::Table).to_owned()) -//! .await -//! } -//! } -//! -//! #[derive(DeriveIden)] -//! pub enum Users { -//! Table, -//! Id, -//! Pid, -//! Email, -//! Name, -//! Password, -//! ResetToken, -//! ResetSentAt, -//! } -//! ``` - -use sea_orm::sea_query::{ - self, Alias, ColumnDef, ColumnType, Expr, Iden, IntoIden, PgInterval, Table, - TableCreateStatement, -}; - -#[derive(Iden)] -enum GeneralIds { - CreatedAt, - UpdatedAt, -} - -/// Wrapping table schema creation. -pub fn table_auto(name: T) -> TableCreateStatement { - timestamps(Table::create().table(name).if_not_exists().take()) -} - -/// Create a primary key column with auto-increment feature. -pub fn pk_auto(name: T) -> ColumnDef { - integer(name).auto_increment().primary_key().take() -} - -/// Create a UUID primary key -pub fn pk_uuid(name: T) -> ColumnDef { - uuid(name).primary_key().take() -} - -pub fn char_len(col: T, length: u32) -> ColumnDef { - ColumnDef::new(col).char_len(length).not_null().take() -} - -pub fn char_len_null(col: T, length: u32) -> ColumnDef { - ColumnDef::new(col).char_len(length).null().take() -} - -pub fn char_len_uniq(col: T, length: u32) -> ColumnDef { - char_len(col, length).unique_key().take() -} - -pub fn char(col: T) -> ColumnDef { - ColumnDef::new(col).char().not_null().take() -} - -pub fn char_null(col: T) -> ColumnDef { - ColumnDef::new(col).char().null().take() -} - -pub fn char_uniq(col: T) -> ColumnDef { - char(col).unique_key().take() -} - -pub fn string_len(col: T, length: u32) -> ColumnDef { - ColumnDef::new(col).string_len(length).not_null().take() -} - -pub fn string_len_null(col: T, length: u32) -> ColumnDef { - ColumnDef::new(col).string_len(length).null().take() -} - -pub fn string_len_uniq(col: T, length: u32) -> ColumnDef { - string_len(col, length).unique_key().take() -} - -pub fn string(col: T) -> ColumnDef { - ColumnDef::new(col).string().not_null().take() -} - -pub fn string_null(col: T) -> ColumnDef { - ColumnDef::new(col).string().null().take() -} - -pub fn string_uniq(col: T) -> ColumnDef { - string(col).unique_key().take() -} - -pub fn text(col: T) -> ColumnDef { - ColumnDef::new(col).text().not_null().take() -} - -pub fn text_null(col: T) -> ColumnDef { - ColumnDef::new(col).text().null().take() -} - -pub fn text_uniq(col: T) -> ColumnDef { - text(col).unique_key().take() -} - -pub fn tiny_integer(col: T) -> ColumnDef { - ColumnDef::new(col).tiny_integer().not_null().take() -} - -pub fn tiny_integer_null(col: T) -> ColumnDef { - ColumnDef::new(col).tiny_integer().null().take() -} - -pub fn tiny_integer_uniq(col: T) -> ColumnDef { - tiny_integer(col).unique_key().take() -} - -pub fn small_integer(col: T) -> ColumnDef { - ColumnDef::new(col).small_integer().not_null().take() -} - -pub fn small_integer_null(col: T) -> ColumnDef { - ColumnDef::new(col).small_integer().null().take() -} - -pub fn small_integer_uniq(col: T) -> ColumnDef { - small_integer(col).unique_key().take() -} - -pub fn integer(col: T) -> ColumnDef { - ColumnDef::new(col).integer().not_null().take() -} - -pub fn integer_null(col: T) -> ColumnDef { - ColumnDef::new(col).integer().null().take() -} - -pub fn integer_uniq(col: T) -> ColumnDef { - integer(col).unique_key().take() -} - -pub fn big_integer(col: T) -> ColumnDef { - ColumnDef::new(col).big_integer().not_null().take() -} - -pub fn big_integer_null(col: T) -> ColumnDef { - ColumnDef::new(col).big_integer().null().take() -} - -pub fn big_integer_uniq(col: T) -> ColumnDef { - big_integer(col).unique_key().take() -} - -pub fn tiny_unsigned(col: T) -> ColumnDef { - ColumnDef::new(col).tiny_unsigned().not_null().take() -} - -pub fn tiny_unsigned_null(col: T) -> ColumnDef { - ColumnDef::new(col).tiny_unsigned().null().take() -} - -pub fn tiny_unsigned_uniq(col: T) -> ColumnDef { - tiny_unsigned(col).unique_key().take() -} - -pub fn small_unsigned(col: T) -> ColumnDef { - ColumnDef::new(col).small_unsigned().not_null().take() -} - -pub fn small_unsigned_null(col: T) -> ColumnDef { - ColumnDef::new(col).small_unsigned().null().take() -} - -pub fn small_unsigned_uniq(col: T) -> ColumnDef { - small_unsigned(col).unique_key().take() -} - -pub fn unsigned(col: T) -> ColumnDef { - ColumnDef::new(col).unsigned().not_null().take() -} - -pub fn unsigned_null(col: T) -> ColumnDef { - ColumnDef::new(col).unsigned().null().take() -} - -pub fn unsigned_uniq(col: T) -> ColumnDef { - unsigned(col).unique_key().take() -} - -pub fn big_unsigned(col: T) -> ColumnDef { - ColumnDef::new(col).big_unsigned().not_null().take() -} - -pub fn big_unsigned_null(col: T) -> ColumnDef { - ColumnDef::new(col).big_unsigned().null().take() -} - -pub fn big_unsigned_uniq(col: T) -> ColumnDef { - big_unsigned(col).unique_key().take() -} - -pub fn float(col: T) -> ColumnDef { - ColumnDef::new(col).float().not_null().take() -} - -pub fn float_null(col: T) -> ColumnDef { - ColumnDef::new(col).float().null().take() -} - -pub fn float_uniq(col: T) -> ColumnDef { - float(col).unique_key().take() -} - -pub fn double(col: T) -> ColumnDef { - ColumnDef::new(col).double().not_null().take() -} - -pub fn double_null(col: T) -> ColumnDef { - ColumnDef::new(col).double().null().take() -} - -pub fn double_uniq(col: T) -> ColumnDef { - double(col).unique_key().take() -} - -pub fn decimal_len(col: T, precision: u32, scale: u32) -> ColumnDef { - ColumnDef::new(col) - .decimal_len(precision, scale) - .not_null() - .take() -} - -pub fn decimal_len_null(col: T, precision: u32, scale: u32) -> ColumnDef { - ColumnDef::new(col) - .decimal_len(precision, scale) - .null() - .take() -} - -pub fn decimal_len_uniq(col: T, precision: u32, scale: u32) -> ColumnDef { - decimal_len(col, precision, scale).unique_key().take() -} - -pub fn decimal(col: T) -> ColumnDef { - ColumnDef::new(col).decimal().not_null().take() -} - -pub fn decimal_null(col: T) -> ColumnDef { - ColumnDef::new(col).decimal().null().take() -} - -pub fn decimal_uniq(col: T) -> ColumnDef { - decimal(col).unique_key().take() -} - -pub fn date_time(col: T) -> ColumnDef { - ColumnDef::new(col).date_time().not_null().take() -} - -pub fn date_time_null(col: T) -> ColumnDef { - ColumnDef::new(col).date_time().null().take() -} - -pub fn date_time_uniq(col: T) -> ColumnDef { - date_time(col).unique_key().take() -} - -pub fn interval( - col: T, - fields: Option, - precision: Option, -) -> ColumnDef { - ColumnDef::new(col) - .interval(fields, precision) - .not_null() - .take() -} - -pub fn interval_null( - col: T, - fields: Option, - precision: Option, -) -> ColumnDef { - ColumnDef::new(col) - .interval(fields, precision) - .null() - .take() -} - -pub fn interval_uniq( - col: T, - fields: Option, - precision: Option, -) -> ColumnDef { - interval(col, fields, precision).unique_key().take() -} - -pub fn timestamp(col: T) -> ColumnDef { - ColumnDef::new(col).timestamp().not_null().take() -} - -pub fn timestamp_null(col: T) -> ColumnDef { - ColumnDef::new(col).timestamp().null().take() -} - -pub fn timestamp_uniq(col: T) -> ColumnDef { - timestamp(col).unique_key().take() -} - -pub fn timestamp_with_time_zone(col: T) -> ColumnDef { - ColumnDef::new(col) - .timestamp_with_time_zone() - .not_null() - .take() -} - -pub fn timestamp_with_time_zone_null(col: T) -> ColumnDef { - ColumnDef::new(col).timestamp_with_time_zone().null().take() -} - -pub fn timestamp_with_time_zone_uniq(col: T) -> ColumnDef { - timestamp_with_time_zone(col).unique_key().take() -} - -pub fn time(col: T) -> ColumnDef { - ColumnDef::new(col).time().not_null().take() -} - -pub fn time_null(col: T) -> ColumnDef { - ColumnDef::new(col).time().null().take() -} - -pub fn time_uniq(col: T) -> ColumnDef { - time(col).unique_key().take() -} - -pub fn date(col: T) -> ColumnDef { - ColumnDef::new(col).date().not_null().take() -} - -pub fn date_null(col: T) -> ColumnDef { - ColumnDef::new(col).date().null().take() -} - -pub fn date_uniq(col: T) -> ColumnDef { - date(col).unique_key().take() -} - -pub fn year(col: T) -> ColumnDef { - ColumnDef::new(col).year().not_null().take() -} - -pub fn year_null(col: T) -> ColumnDef { - ColumnDef::new(col).year().null().take() -} - -pub fn year_uniq(col: T) -> ColumnDef { - year(col).unique_key().take() -} - -pub fn binary_len(col: T, length: u32) -> ColumnDef { - ColumnDef::new(col).binary_len(length).not_null().take() -} - -pub fn binary_len_null(col: T, length: u32) -> ColumnDef { - ColumnDef::new(col).binary_len(length).null().take() -} - -pub fn binary_len_uniq(col: T, length: u32) -> ColumnDef { - binary_len(col, length).unique_key().take() -} - -pub fn binary(col: T) -> ColumnDef { - ColumnDef::new(col).binary().not_null().take() -} - -pub fn binary_null(col: T) -> ColumnDef { - ColumnDef::new(col).binary().null().take() -} - -pub fn binary_uniq(col: T) -> ColumnDef { - binary(col).unique_key().take() -} - -pub fn var_binary(col: T, length: u32) -> ColumnDef { - ColumnDef::new(col).var_binary(length).not_null().take() -} - -pub fn var_binary_null(col: T, length: u32) -> ColumnDef { - ColumnDef::new(col).var_binary(length).null().take() -} - -pub fn var_binary_uniq(col: T, length: u32) -> ColumnDef { - var_binary(col, length).unique_key().take() -} - -pub fn bit(col: T, length: Option) -> ColumnDef { - ColumnDef::new(col).bit(length).not_null().take() -} - -pub fn bit_null(col: T, length: Option) -> ColumnDef { - ColumnDef::new(col).bit(length).null().take() -} - -pub fn bit_uniq(col: T, length: Option) -> ColumnDef { - bit(col, length).unique_key().take() -} - -pub fn varbit(col: T, length: u32) -> ColumnDef { - ColumnDef::new(col).varbit(length).not_null().take() -} - -pub fn varbit_null(col: T, length: u32) -> ColumnDef { - ColumnDef::new(col).varbit(length).null().take() -} - -pub fn varbit_uniq(col: T, length: u32) -> ColumnDef { - varbit(col, length).unique_key().take() -} - -pub fn blob(col: T) -> ColumnDef { - ColumnDef::new(col).blob().not_null().take() -} - -pub fn blob_null(col: T) -> ColumnDef { - ColumnDef::new(col).blob().null().take() -} - -pub fn blob_uniq(col: T) -> ColumnDef { - blob(col).unique_key().take() -} - -pub fn boolean(col: T) -> ColumnDef { - ColumnDef::new(col).boolean().not_null().take() -} - -pub fn boolean_null(col: T) -> ColumnDef { - ColumnDef::new(col).boolean().null().take() -} - -pub fn boolean_uniq(col: T) -> ColumnDef { - boolean(col).unique_key().take() -} - -pub fn money_len(col: T, precision: u32, scale: u32) -> ColumnDef { - ColumnDef::new(col) - .money_len(precision, scale) - .not_null() - .take() -} - -pub fn money_len_null(col: T, precision: u32, scale: u32) -> ColumnDef { - ColumnDef::new(col) - .money_len(precision, scale) - .null() - .take() -} - -pub fn money_len_uniq(col: T, precision: u32, scale: u32) -> ColumnDef { - money_len(col, precision, scale).unique_key().take() -} - -pub fn money(col: T) -> ColumnDef { - ColumnDef::new(col).money().not_null().take() -} - -pub fn money_null(col: T) -> ColumnDef { - ColumnDef::new(col).money().null().take() -} - -pub fn money_uniq(col: T) -> ColumnDef { - money(col).unique_key().take() -} - -pub fn json(col: T) -> ColumnDef { - ColumnDef::new(col).json().not_null().take() -} - -pub fn json_null(col: T) -> ColumnDef { - ColumnDef::new(col).json().null().take() -} - -pub fn json_uniq(col: T) -> ColumnDef { - json(col).unique_key().take() -} - -pub fn json_binary(col: T) -> ColumnDef { - ColumnDef::new(col).json_binary().not_null().take() -} - -pub fn json_binary_null(col: T) -> ColumnDef { - ColumnDef::new(col).json_binary().null().take() -} - -pub fn json_binary_uniq(col: T) -> ColumnDef { - json_binary(col).unique_key().take() -} - -pub fn uuid(col: T) -> ColumnDef { - ColumnDef::new(col).uuid().not_null().take() -} - -pub fn uuid_null(col: T) -> ColumnDef { - ColumnDef::new(col).uuid().null().take() -} - -pub fn uuid_uniq(col: T) -> ColumnDef { - uuid(col).unique_key().take() -} - -pub fn custom(col: T, name: N) -> ColumnDef { - ColumnDef::new(col).custom(name).not_null().take() -} - -pub fn custom_null(col: T, name: N) -> ColumnDef { - ColumnDef::new(col).custom(name).null().take() -} - -pub fn enumeration(col: T, name: N, variants: V) -> ColumnDef -where - T: IntoIden, - N: IntoIden, - S: IntoIden, - V: IntoIterator, -{ - ColumnDef::new(col) - .enumeration(name, variants) - .not_null() - .take() -} - -pub fn enumeration_null(col: T, name: N, variants: V) -> ColumnDef -where - T: IntoIden, - N: IntoIden, - S: IntoIden, - V: IntoIterator, -{ - ColumnDef::new(col) - .enumeration(name, variants) - .null() - .take() -} - -pub fn enumeration_uniq(col: T, name: N, variants: V) -> ColumnDef -where - T: IntoIden, - N: IntoIden, - S: IntoIden, - V: IntoIterator, -{ - enumeration(col, name, variants).unique_key().take() -} - -pub fn array(col: T, elem_type: ColumnType) -> ColumnDef { - ColumnDef::new(col).array(elem_type).not_null().take() -} - -pub fn array_null(col: T, elem_type: ColumnType) -> ColumnDef { - ColumnDef::new(col).array(elem_type).null().take() -} - -pub fn array_uniq(col: T, elem_type: ColumnType) -> ColumnDef { - array(col, elem_type).unique_key().take() -} - -/// Añade las columnas de timestamp (`CreatedAt` y `UpdatedAt`) a una tabla existente. -pub fn timestamps(t: TableCreateStatement) -> TableCreateStatement { - let mut t = t; - t.col(timestamp(GeneralIds::CreatedAt).default(Expr::current_timestamp())) - .col(timestamp(GeneralIds::UpdatedAt).default(Expr::current_timestamp())) - .take() -} - -/// Crea un alias. -pub fn name>(name: T) -> Alias { - Alias::new(name) -} diff --git a/extensions/pagetop-seaorm/src/migration/seaql_migrations.rs b/extensions/pagetop-seaorm/src/migration/seaql_migrations.rs deleted file mode 100644 index 51da9300..00000000 --- a/extensions/pagetop-seaorm/src/migration/seaql_migrations.rs +++ /dev/null @@ -1,15 +0,0 @@ -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] -// One should override the name of migration table via `MigratorTrait::migration_table_name` method -#[sea_orm(table_name = "seaql_migrations")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub version: String, - pub applied_at: i64, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation {} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/tools/changelog.sh b/tools/changelog.sh index fc2a8a0c..36fd8f9b 100755 --- a/tools/changelog.sh +++ b/tools/changelog.sh @@ -65,7 +65,6 @@ case "$CRATE" in # Extensions --exclude-path "extensions/pagetop-aliner/**/*" --exclude-path "extensions/pagetop-bootsier/**/*" - --exclude-path "extensions/pagetop-seaorm/**/*" ) ;; pagetop-aliner) @@ -76,10 +75,6 @@ case "$CRATE" in CHANGELOG_FILE="extensions/pagetop-bootsier/CHANGELOG.md" PATH_FLAGS=(--include-path "extensions/pagetop-bootsier/**/*") ;; - pagetop-seaorm) - CHANGELOG_FILE="extensions/pagetop-seaorm/CHANGELOG.md" - PATH_FLAGS=(--include-path "extensions/pagetop-seaorm/**/*") - ;; *) echo "Error: unsupported crate '$CRATE'" >&2 exit 1 @@ -125,9 +120,7 @@ read -r -p "Do you want to proceed with the release of $CRATE? [y/N] " REPLY echo "" if [[ ! "$REPLY" =~ ^[Yy]$ ]]; then echo "Aborting release process." >&2 - if [[ -n "${PAGETOP_RESTORE_TREE:-}" ]]; then - git restore --worktree -- . - fi + git restore --worktree -- . exit 1 fi diff --git a/tools/release.sh b/tools/release.sh index 5234c849..92257b32 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -43,8 +43,6 @@ cd "$(dirname "$0")/.." || exit 1 # ------------------------------------------------------------------------------ # DRY-RUN (por defecto) o ejecución real con --execute # ------------------------------------------------------------------------------ -export PAGETOP_RESTORE_TREE=1 - if [[ "$EXECUTE" != "--execute" ]]; then echo "Running dry-run (default mode). Add --execute to publish" cargo release --config "$CONFIG" --package "$CRATE" "$LEVEL"