Compare commits
3 Commits
6138e4b2b3
...
d05d660198
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d05d660198 | ||
|
|
829c4ef3e3 | ||
|
|
373065c95f |
210
Cargo.lock
generated
210
Cargo.lock
generated
@@ -8,7 +8,7 @@ version = "0.7.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
|
checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.2.16",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
@@ -410,6 +410,22 @@ version = "0.7.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cli"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"clap",
|
||||||
|
"container-simulate",
|
||||||
|
"migration",
|
||||||
|
"once_cell",
|
||||||
|
"path-clean",
|
||||||
|
"shared",
|
||||||
|
"testcontainers",
|
||||||
|
"tokio",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
@@ -444,6 +460,16 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
@@ -737,6 +763,12 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filetime"
|
name = "filetime"
|
||||||
version = "0.2.26"
|
version = "0.2.26"
|
||||||
@@ -778,6 +810,21 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
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]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
@@ -914,6 +961,18 @@ dependencies = [
|
|||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi",
|
||||||
|
"wasip2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@@ -1440,6 +1499,7 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
|||||||
name = "migration"
|
name = "migration"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"sea-orm-cli",
|
||||||
"sea-orm-migration",
|
"sea-orm-migration",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
@@ -1455,6 +1515,23 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "native-tls"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"openssl",
|
||||||
|
"openssl-probe",
|
||||||
|
"openssl-sys",
|
||||||
|
"schannel",
|
||||||
|
"security-framework 2.11.1",
|
||||||
|
"security-framework-sys",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "num-bigint"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
@@ -1529,12 +1606,50 @@ version = "1.70.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl"
|
||||||
|
version = "0.10.75"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.10.0",
|
||||||
|
"cfg-if",
|
||||||
|
"foreign-types",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"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 2.0.110",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-probe"
|
name = "openssl-probe"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.9.111"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "4.6.0"
|
version = "4.6.0"
|
||||||
@@ -1691,6 +1806,16 @@ version = "0.3.32"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pluralizer"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b3eba432a00a1f6c16f39147847a870e94e2e9b992759b503e330efec778cbe"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "potential_utf"
|
name = "potential_utf"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
@@ -1715,6 +1840,16 @@ dependencies = [
|
|||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prettyplease"
|
||||||
|
version = "0.2.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"syn 2.0.110",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "3.4.0"
|
version = "3.4.0"
|
||||||
@@ -1797,6 +1932,12 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "r-efi"
|
||||||
|
version = "5.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "radium"
|
name = "radium"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@@ -1830,7 +1971,7 @@ version = "0.6.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.2.16",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1917,7 +2058,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"getrandom",
|
"getrandom 0.2.16",
|
||||||
"libc",
|
"libc",
|
||||||
"untrusted",
|
"untrusted",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
@@ -2024,7 +2165,7 @@ dependencies = [
|
|||||||
"openssl-probe",
|
"openssl-probe",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"schannel",
|
"schannel",
|
||||||
"security-framework",
|
"security-framework 3.5.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2164,6 +2305,7 @@ dependencies = [
|
|||||||
"glob",
|
"glob",
|
||||||
"indoc",
|
"indoc",
|
||||||
"regex",
|
"regex",
|
||||||
|
"sea-orm-codegen",
|
||||||
"sea-schema",
|
"sea-schema",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -2172,6 +2314,22 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sea-orm-codegen"
|
||||||
|
version = "2.0.0-rc.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "004eff55e5aa46d43ef4f1b3650cef08ae74305c029a52ab036e36fd3ccbd44b"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.5.0",
|
||||||
|
"pluralizer",
|
||||||
|
"prettyplease",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"sea-query",
|
||||||
|
"syn 2.0.110",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sea-orm-macros"
|
name = "sea-orm-macros"
|
||||||
version = "2.0.0-rc.18"
|
version = "2.0.0-rc.18"
|
||||||
@@ -2280,6 +2438,19 @@ version = "4.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "2.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.10.0",
|
||||||
|
"core-foundation 0.9.4",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "3.5.1"
|
version = "3.5.1"
|
||||||
@@ -2287,7 +2458,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef"
|
checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.10.0",
|
"bitflags 2.10.0",
|
||||||
"core-foundation",
|
"core-foundation 0.10.1",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
@@ -2546,6 +2717,7 @@ dependencies = [
|
|||||||
"indexmap 2.12.0",
|
"indexmap 2.12.0",
|
||||||
"log",
|
"log",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
"native-tls",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rust_decimal",
|
"rust_decimal",
|
||||||
@@ -2822,6 +2994,19 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempfile"
|
||||||
|
version = "3.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
|
||||||
|
dependencies = [
|
||||||
|
"fastrand",
|
||||||
|
"getrandom 0.3.4",
|
||||||
|
"once_cell",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys 0.61.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "testcontainers"
|
name = "testcontainers"
|
||||||
version = "0.24.0"
|
version = "0.24.0"
|
||||||
@@ -3209,6 +3394,15 @@ version = "0.11.1+wasi-snapshot-preview1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasip2"
|
||||||
|
version = "1.0.1+wasi-0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasite"
|
name = "wasite"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -3609,6 +3803,12 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.46.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "writeable"
|
name = "writeable"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"apps/container",
|
"apps/container",
|
||||||
"apps/shared",
|
"apps/cli",
|
||||||
|
"public/shared",
|
||||||
"public/database",
|
"public/database",
|
||||||
"public/migration"
|
"public/migration"
|
||||||
]
|
]
|
||||||
|
|||||||
16
apps/cli/Cargo.toml
Normal file
16
apps/cli/Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "cli"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
async-trait = "0.1.89"
|
||||||
|
container-simulate = { path = "../container" }
|
||||||
|
migration = {path = "../../public/migration"}
|
||||||
|
shared = {path = "../../public/shared"}
|
||||||
|
testcontainers = "0.24.0"
|
||||||
|
tokio = { version = "1.47.0", features = ["full"] }
|
||||||
|
url = "2.5.7"
|
||||||
|
clap = { version = "4.5.48", features = ["derive", "env"] }
|
||||||
|
path-clean = "1.0.1"
|
||||||
|
once_cell = "1.21.3"
|
||||||
45
apps/cli/src/cmd.rs
Normal file
45
apps/cli/src/cmd.rs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
use std::pin::Pin;
|
||||||
|
use std::{future::Future, process::exit};
|
||||||
|
|
||||||
|
use clap::{ArgMatches, Command};
|
||||||
|
|
||||||
|
pub mod db_migrate_and_generate;
|
||||||
|
|
||||||
|
pub struct CliCommand {
|
||||||
|
pub command: Command,
|
||||||
|
pub action: fn(&clap::ArgMatches) -> Pin<Box<dyn std::future::Future<Output = ()> + Send>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
static CLI_COMMANDS: once_cell::sync::Lazy<
|
||||||
|
[CliCommand; 1 /* Update this count when adding new commands */],
|
||||||
|
> =
|
||||||
|
once_cell::sync::Lazy::new(|| {
|
||||||
|
[
|
||||||
|
// Add new commands here
|
||||||
|
db_migrate_and_generate::get_cli_command(),
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn get_command() -> Command {
|
||||||
|
let mut c = Command::new("cmd");
|
||||||
|
|
||||||
|
for cmd in CLI_COMMANDS.iter() {
|
||||||
|
c = c.subcommand(cmd.command.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute(matches: &ArgMatches, help_msg: &str) -> Pin<Box<dyn Future<Output = ()> + Send>> {
|
||||||
|
if let Some((subcommand_name, subcommand_matches)) = matches.subcommand() {
|
||||||
|
for cmd in CLI_COMMANDS.iter() {
|
||||||
|
if cmd.command.get_name() == subcommand_name {
|
||||||
|
return (cmd.action)(subcommand_matches);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eprintln!("Error: No valid subcommand provided.");
|
||||||
|
eprintln!("{}", help_msg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
169
apps/cli/src/cmd/db_migrate_and_generate.rs
Normal file
169
apps/cli/src/cmd/db_migrate_and_generate.rs
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
use clap::{Arg, Command};
|
||||||
|
use container::{
|
||||||
|
db::{DBInfo, sqlite::SQLiteContainer},
|
||||||
|
types::ConfigInfoType,
|
||||||
|
};
|
||||||
|
use migration::{generate_entity, migrate_database};
|
||||||
|
use shared::db_type::DBType;
|
||||||
|
|
||||||
|
use crate::cmd::CliCommand;
|
||||||
|
|
||||||
|
const MAX_DB_READY_ATTEMPTS: u8 = 10;
|
||||||
|
const DB_READY_CHECK_INTERVAL_SECS: u64 = 2;
|
||||||
|
const DB_READY_STRING: [&str; 1] = ["ready to accept connections"];
|
||||||
|
|
||||||
|
pub fn get_cli_command() -> CliCommand {
|
||||||
|
CliCommand {
|
||||||
|
command: command(),
|
||||||
|
action: action,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn command() -> Command {
|
||||||
|
Command::new("db:migrate_and_generate")
|
||||||
|
.arg(
|
||||||
|
Arg::new("output_path")
|
||||||
|
.short('o')
|
||||||
|
.long("output-path")
|
||||||
|
.value_name("PATH")
|
||||||
|
.help("Path to output the generated entity schema")
|
||||||
|
.required(true),
|
||||||
|
)
|
||||||
|
.about("Migrate database and generate entity schema")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn action(
|
||||||
|
_matches: &clap::ArgMatches,
|
||||||
|
) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send>> {
|
||||||
|
let output_path = _matches.get_one::<String>("output_path");
|
||||||
|
let output_path = output_path.unwrap().to_string();
|
||||||
|
Box::pin(async move {
|
||||||
|
let mut error_occurred = false;
|
||||||
|
let database_configs = vec![
|
||||||
|
SQLiteContainer::new(None)
|
||||||
|
.await
|
||||||
|
.get_db_container_config_info()
|
||||||
|
.await,
|
||||||
|
// only sqlite is required to generate entities when using Seaorm
|
||||||
|
// PostgreSQLContainer::new(None)
|
||||||
|
// .await
|
||||||
|
// .get_db_container_config_info()
|
||||||
|
// .await,
|
||||||
|
];
|
||||||
|
|
||||||
|
for db_config in database_configs {
|
||||||
|
let config = container::Config {
|
||||||
|
database: db_config,
|
||||||
|
};
|
||||||
|
let mut detached_handler = container::start_detached(&config).await;
|
||||||
|
match migrate_and_generate_entity(&config, &output_path).await {
|
||||||
|
Ok(_) => println!("Migration and entity generation succeeded."),
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!("Migration and entity generation failed.");
|
||||||
|
error_occurred = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detached_handler.stop().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
if error_occurred {
|
||||||
|
std::process::exit(1);
|
||||||
|
} else {
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn migrate_and_generate_entity(
|
||||||
|
config: &container::Config,
|
||||||
|
output_path: &str,
|
||||||
|
) -> Result<(), ()> {
|
||||||
|
let ready_result = await_database_ready(&config).await;
|
||||||
|
if ready_result.is_err() {
|
||||||
|
eprintln!("Database did not become ready in time.");
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let db_url = match &config.database {
|
||||||
|
ConfigInfoType::Containerized(container_info) => &container_info.url,
|
||||||
|
ConfigInfoType::PreExisting(pre_existing_info) => &pre_existing_info.url,
|
||||||
|
};
|
||||||
|
|
||||||
|
let db_type = get_database_type(&config);
|
||||||
|
match migrate_database(db_url).await {
|
||||||
|
Ok(_) => {
|
||||||
|
println!("Database migrated successfully for {:?}", db_type);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Failed to migrate database for {}: {:#?}", db_type, e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match generate_entity(db_url, output_path).await {
|
||||||
|
Ok(_) => {
|
||||||
|
println!(
|
||||||
|
"Database entity schema generated successfully for {:?}",
|
||||||
|
db_type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!(
|
||||||
|
"Failed to generate database entity schema for {}: {:#?}",
|
||||||
|
db_type, e
|
||||||
|
);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_database_type(config: &container::Config) -> DBType {
|
||||||
|
match config.database {
|
||||||
|
ConfigInfoType::Containerized(ref container_info) => container_info.db_type.clone(),
|
||||||
|
ConfigInfoType::PreExisting(ref pre_existing_info) => pre_existing_info.db_type.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn await_database_ready(config: &container::Config) -> Result<(), ()> {
|
||||||
|
match config.database {
|
||||||
|
ConfigInfoType::Containerized(ref container_info) => {
|
||||||
|
let container_type = &container_info.db_type;
|
||||||
|
for attempt in 1..=MAX_DB_READY_ATTEMPTS {
|
||||||
|
println!(
|
||||||
|
"Checking if database container {} is ready (attempt {}/{})...",
|
||||||
|
container_info.db_type, attempt, MAX_DB_READY_ATTEMPTS
|
||||||
|
);
|
||||||
|
let logs = match container_info.container.stdout_to_vec().await {
|
||||||
|
Ok(logs) => logs,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Failed to get container logs: {}", e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let log_output = String::from_utf8_lossy(&logs);
|
||||||
|
if DB_READY_STRING.iter().any(|&s| log_output.contains(s)) {
|
||||||
|
println!("Database container {} is ready.", container_info.db_type);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
tokio::time::sleep(std::time::Duration::from_secs(DB_READY_CHECK_INTERVAL_SECS))
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
eprintln!(
|
||||||
|
"Database container {} did not become ready after {} attempts.",
|
||||||
|
container_type, MAX_DB_READY_ATTEMPTS
|
||||||
|
);
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigInfoType::PreExisting(ref pre_existing_info) => {
|
||||||
|
println!(
|
||||||
|
"Pre-existing database of type {} assumed to be ready.",
|
||||||
|
pre_existing_info.db_type
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
apps/cli/src/main.rs
Normal file
22
apps/cli/src/main.rs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
mod cmd;
|
||||||
|
|
||||||
|
use clap::error::ErrorKind;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let mut command = cmd::get_command();
|
||||||
|
let help_output = format!("{}", command.render_help());
|
||||||
|
let matches = command
|
||||||
|
.try_get_matches()
|
||||||
|
.unwrap_or_else(|err| match err.kind() {
|
||||||
|
ErrorKind::DisplayHelp | ErrorKind::DisplayVersion => {
|
||||||
|
err.print().expect("Error writing Error");
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
err.print().expect("Error writing Error");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cmd::execute(&matches, &help_output).await;
|
||||||
|
}
|
||||||
19
justfile
19
justfile
@@ -1,6 +1,15 @@
|
|||||||
set dotenv-load := true
|
set dotenv-load := true
|
||||||
|
# development environment file
|
||||||
set dotenv-filename := "./public/database/.env.generated"
|
set dotenv-filename := "./public/database/.env.generated"
|
||||||
|
|
||||||
|
cli *args:
|
||||||
|
cd apps/cli && \
|
||||||
|
if [ -n "{{args}}" ]; then \
|
||||||
|
cargo run -- {{args}}; \
|
||||||
|
else \
|
||||||
|
cargo run; \
|
||||||
|
fi
|
||||||
|
|
||||||
simulate *args:
|
simulate *args:
|
||||||
cd apps/container && \
|
cd apps/container && \
|
||||||
if [ -n "{{args}}" ]; then \
|
if [ -n "{{args}}" ]; then \
|
||||||
@@ -29,11 +38,5 @@ migrate *args:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
generate-entity:
|
generate-entity:
|
||||||
# load development environment variables
|
# delegate to cli
|
||||||
# sea-orm-cli will also load .env file by default
|
just cli db:migrate_and_generate --output-path ../../public/database/src/generated/entities
|
||||||
cd public/migration && \
|
|
||||||
sea-orm-cli generate entity \
|
|
||||||
-o ../database/src/generated/entities \
|
|
||||||
--with-serde both \
|
|
||||||
--date-time-crate chrono
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,17 +3,15 @@
|
|||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[sea_orm::model]
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
#[sea_orm(table_name = "config")]
|
#[sea_orm(table_name = "config")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(unique, primary_key, auto_increment = false)]
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
pub key: String,
|
pub key: String,
|
||||||
pub value: String,
|
pub value: String,
|
||||||
pub created_at: DateTimeUtc,
|
pub created_at: DateTimeUtc,
|
||||||
pub updated_at: DateTimeUtc,
|
pub updated_at: DateTimeUtc,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
|
||||||
pub enum Relation {}
|
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[sea_orm::model]
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
#[sea_orm(table_name = "user")]
|
#[sea_orm(table_name = "user")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
@@ -17,7 +18,4 @@ pub struct Model {
|
|||||||
pub updated_at: DateTimeUtc,
|
pub updated_at: DateTimeUtc,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
|
||||||
pub enum Relation {}
|
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ path = "src/lib.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread"] }
|
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread"] }
|
||||||
|
sea-orm-cli = { version = "2.0.0-rc", features = ["sqlx-postgres", "sqlx-mysql", "sqlx-sqlite", "runtime-tokio"] }
|
||||||
|
|
||||||
[dependencies.sea-orm-migration]
|
[dependencies.sea-orm-migration]
|
||||||
version = "2.0.0-rc"
|
version = "2.0.0-rc"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ pub use sea_orm_migration::prelude::*;
|
|||||||
|
|
||||||
mod migrations;
|
mod migrations;
|
||||||
use migrations::*;
|
use migrations::*;
|
||||||
|
use sea_orm_migration::sea_orm::Database;
|
||||||
|
|
||||||
pub struct Migrator;
|
pub struct Migrator;
|
||||||
|
|
||||||
@@ -14,3 +15,49 @@ impl MigratorTrait for Migrator {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn migrate_database(db_url: &str) -> Result<(), DbErr> {
|
||||||
|
let db = Database::connect(db_url).await?;
|
||||||
|
Migrator::up(&db, None).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn generate_entity(
|
||||||
|
db_url: &str,
|
||||||
|
output_dir: &str,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
use sea_orm_cli::commands::generate::run_generate_command;
|
||||||
|
run_generate_command(
|
||||||
|
sea_orm_cli::GenerateSubcommands::Entity {
|
||||||
|
compact_format: true,
|
||||||
|
expanded_format: false,
|
||||||
|
frontend_format: false,
|
||||||
|
include_hidden_tables: false,
|
||||||
|
tables: vec![],
|
||||||
|
ignore_tables: vec!["seaql_migrations".to_string()],
|
||||||
|
max_connections: 1,
|
||||||
|
acquire_timeout: 30,
|
||||||
|
output_dir: output_dir.to_string(),
|
||||||
|
database_schema: Some("public".to_string()),
|
||||||
|
database_url: db_url.to_string(),
|
||||||
|
with_prelude: "all".to_string(),
|
||||||
|
with_serde: "both".to_string(),
|
||||||
|
serde_skip_deserializing_primary_key: false,
|
||||||
|
serde_skip_hidden_column: false,
|
||||||
|
with_copy_enums: true,
|
||||||
|
date_time_crate: sea_orm_cli::DateTimeCrate::Chrono,
|
||||||
|
lib: false,
|
||||||
|
model_extra_derives: vec![],
|
||||||
|
model_extra_attributes: vec![],
|
||||||
|
enum_extra_derives: vec![],
|
||||||
|
enum_extra_attributes: vec![],
|
||||||
|
seaography: false,
|
||||||
|
impl_active_model_behavior: true,
|
||||||
|
big_integer_type: sea_orm_cli::BigIntegerType::I64,
|
||||||
|
column_extra_derives: vec![],
|
||||||
|
entity_format: Some("dense".to_string()),
|
||||||
|
preserve_user_modifications: false,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user