diff --git a/docs/.gitignore b/docs/.gitignore index 9e337a15..173ebac0 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,2 +1,3 @@ .vitepress/dist/ .vitepress/cache/ +.vitepress/.temp/ diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 6428314e..f58322d3 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -3,7 +3,7 @@ import { defineConfig } from "vitepress" export default defineConfig({ title: "VaultLink", description: "Self-hosted real-time synchronisation for Obsidian", - base: "/vault-link/", + base: "/", themeConfig: { logo: "/logo.svg", nav: [ @@ -56,5 +56,5 @@ export default defineConfig({ provider: "local" } }, - head: [["link", { rel: "icon", type: "image/svg+xml", href: "/vault-link/logo.svg" }]] + head: [["link", { rel: "icon", type: "image/svg+xml", href: "/logo.svg" }]] }) diff --git a/docs/architecture/data-flow.md b/docs/architecture/data-flow.md index 832c5624..167be524 100644 --- a/docs/architecture/data-flow.md +++ b/docs/architecture/data-flow.md @@ -361,11 +361,11 @@ VALUES (?, ?, ?); ```json { - "type": "upload_file", - "path": "notes/example.md", - "content": "File content here...", - "base_version": 10, - "timestamp": "2024-01-01T12:00:00Z" + "type": "upload_file", + "path": "notes/example.md", + "content": "File content here...", + "base_version": 10, + "timestamp": "2024-01-01T12:00:00Z" } ``` @@ -373,8 +373,8 @@ VALUES (?, ?, ?); ```json { - "type": "download_file", - "path": "notes/example.md" + "type": "download_file", + "path": "notes/example.md" } ``` @@ -382,8 +382,8 @@ VALUES (?, ?, ?); ```json { - "type": "delete_file", - "path": "notes/old.md" + "type": "delete_file", + "path": "notes/old.md" } ``` @@ -391,8 +391,8 @@ VALUES (?, ?, ?); ```json { - "type": "list_files", - "since_version": 0 + "type": "list_files", + "since_version": 0 } ``` @@ -402,11 +402,11 @@ VALUES (?, ?, ?); ```json { - "type": "file_updated", - "path": "notes/example.md", - "version": 11, - "size": 1024, - "hash": "abc123..." + "type": "file_updated", + "path": "notes/example.md", + "version": 11, + "size": 1024, + "hash": "abc123..." } ``` @@ -414,10 +414,10 @@ VALUES (?, ?, ?); ```json { - "type": "file_content", - "path": "notes/example.md", - "content": "Updated content...", - "version": 11 + "type": "file_content", + "path": "notes/example.md", + "content": "Updated content...", + "version": 11 } ``` @@ -425,9 +425,9 @@ VALUES (?, ?, ?); ```json { - "type": "file_deleted", - "path": "notes/old.md", - "version": 12 + "type": "file_deleted", + "path": "notes/old.md", + "version": 12 } ``` @@ -435,9 +435,9 @@ VALUES (?, ?, ?); ```json { - "type": "sync_complete", - "total_files": 150, - "current_version": 200 + "type": "sync_complete", + "total_files": 150, + "current_version": 200 } ``` @@ -445,9 +445,9 @@ VALUES (?, ?, ?); ```json { - "type": "error", - "message": "File too large", - "code": "FILE_TOO_LARGE" + "type": "error", + "message": "File too large", + "code": "FILE_TOO_LARGE" } ``` diff --git a/docs/config/authentication.md b/docs/config/authentication.md index 11425b5b..74977be7 100644 --- a/docs/config/authentication.md +++ b/docs/config/authentication.md @@ -243,9 +243,9 @@ users: 2. Client sends authentication message: ```json { - "type": "auth", - "token": "user-token", - "vault": "vault-name" + "type": "auth", + "token": "user-token", + "vault": "vault-name" } ``` 3. Server validates: diff --git a/scripts/check.sh b/scripts/check.sh index dd41fbcb..b046fb10 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -32,13 +32,24 @@ else npm ci fi -cd .. -cd frontend npm run build npm run test npm run lint +cd ../docs + +if [[ "$FIX_MODE" == true ]]; then + npm install + npm run format + npm run spell +else + npm ci + npm run format:check + npm run spell:check +fi + +cd .. # Use git ls-files to only check tracked files, respecting .gitignore # We always run in fix mode and then check with git status git ls-files | xargs npx eclint fix @@ -51,8 +62,4 @@ fi cd .. -if [[ "$FIX_MODE" == true ]]; then - $0 -else - echo "Success" -fi +echo "Success" diff --git a/sync-server/Cargo.lock b/sync-server/Cargo.lock index c07ddb17..81c1c453 100644 --- a/sync-server/Cargo.lock +++ b/sync-server/Cargo.lock @@ -17,6 +17,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + [[package]] name = "aho-corasick" version = "1.1.3" @@ -114,7 +120,7 @@ checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -224,7 +230,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -256,7 +262,7 @@ dependencies = [ "heck", "proc-macro-error", "quote", - "syn 2.0.90", + "syn 2.0.111", "ubyte", ] @@ -341,6 +347,8 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -396,7 +404,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -432,6 +440,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "cpufeatures" version = "0.2.16" @@ -456,6 +473,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-queue" version = "0.3.11" @@ -502,7 +528,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -513,9 +539,15 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.90", + "syn 2.0.111", ] +[[package]] +name = "dary_heap" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06d2e3287df1c007e74221c49ca10a95d557349e54b3a75dc2fb14712c751f04" + [[package]] name = "data-encoding" version = "2.6.0" @@ -553,7 +585,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -647,6 +679,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -723,7 +761,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -803,7 +841,18 @@ checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", ] [[package]] @@ -812,7 +861,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown", + "hashbrown 0.15.2", ] [[package]] @@ -1113,7 +1162,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -1143,6 +1192,43 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "include-flate" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01b7cb6ca682a621e7cda1c358c9724b53a7b4409be9be1dd443b7f3a26f998" +dependencies = [ + "include-flate-codegen", + "include-flate-compress", + "libflate", + "zstd", +] + +[[package]] +name = "include-flate-codegen" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f49bf5274aebe468d6e6eba14a977eaf1efa481dc173f361020de70c1c48050" +dependencies = [ + "include-flate-compress", + "libflate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.111", + "zstd", +] + +[[package]] +name = "include-flate-compress" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae6a40e716bcd5931f5dbb79cd921512a4f647e2e9413fded3171fca3824dbc" +dependencies = [ + "libflate", + "zstd", +] + [[package]] name = "indexmap" version = "2.7.0" @@ -1150,7 +1236,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.2", ] [[package]] @@ -1165,6 +1251,16 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.2", + "libc", +] + [[package]] name = "js-sys" version = "0.3.76" @@ -1190,6 +1286,30 @@ version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +[[package]] +name = "libflate" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3248b8d211bd23a104a42d81b4fa8bb8ac4a3b75e7a43d85d2c9ccb6179cd74" +dependencies = [ + "adler32", + "core2", + "crc32fast", + "dary_heap", + "libflate_lz77", +] + +[[package]] +name = "libflate_lz77" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a599cb10a9cd92b1300debcef28da8f70b935ec937f44fcd1b70a7c986a11c5c" +dependencies = [ + "core2", + "hashbrown 0.16.1", + "rle-decode-fast", +] + [[package]] name = "libm" version = "0.2.11" @@ -1272,6 +1392,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.8.0" @@ -1498,18 +1628,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -1628,6 +1758,12 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rle-decode-fast" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" + [[package]] name = "rsa" version = "0.9.7" @@ -1648,6 +1784,41 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rust-embed" +version = "8.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "947d7f3fad52b283d261c4c99a084937e2fe492248cb9a68a8435a861b8798ca" +dependencies = [ + "include-flate", + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fa2c8c9e8711e10f9c4fd2d64317ef13feaab820a4c51541f1a8c8e2e851ab2" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.111", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b161f275cb337fe0a44d924a5f4df0ed69c2c39519858f931ce61c779d3475" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1679,6 +1850,15 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "sanitize-filename" version = "0.6.0" @@ -1721,7 +1901,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -1905,7 +2085,7 @@ dependencies = [ "futures-intrusive", "futures-io", "futures-util", - "hashbrown", + "hashbrown 0.15.2", "hashlink", "indexmap", "log", @@ -1934,7 +2114,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -1957,7 +2137,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.90", + "syn 2.0.111", "tokio", "url", ] @@ -2112,9 +2292,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", @@ -2136,9 +2316,11 @@ dependencies = [ "futures", "humantime-serde", "log", + "mime_guess", "rand 0.9.0", "reconcile-text", "regex", + "rust-embed", "sanitize-filename", "serde", "serde_json", @@ -2167,7 +2349,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -2218,7 +2400,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -2229,7 +2411,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -2292,7 +2474,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -2384,7 +2566,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -2447,7 +2629,7 @@ checksum = "0e9d8656589772eeec2cf7a8264d9cda40fb28b9bc53118ceb9e8c07f8f38730" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", "termcolor", ] @@ -2481,6 +2663,12 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f720def6ce1ee2fc44d40ac9ed6d3a59c361c80a75a7aa8e75bb9baed31cf2ea" +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-bidi" version = "0.3.17" @@ -2577,6 +2765,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2619,7 +2817,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", "wasm-bindgen-shared", ] @@ -2641,7 +2839,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2890,7 +3088,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", "synstructure", ] @@ -2921,7 +3119,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -2932,7 +3130,7 @@ checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", ] [[package]] @@ -2952,7 +3150,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", "synstructure", ] @@ -2981,5 +3179,33 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.111", +] + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", ] diff --git a/sync-server/Cargo.toml b/sync-server/Cargo.toml index 394ff314..df63c2fa 100644 --- a/sync-server/Cargo.toml +++ b/sync-server/Cargo.toml @@ -34,6 +34,8 @@ bimap = "0.6.3" ts-rs = { version = "10.1", features = ["uuid-impl", "chrono-impl"] } base64 = "0.22.1" reconcile-text = { version = "0.8.0", features = ["serde"] } +rust-embed = { version = "8.5.0", features = ["compression"] } +mime_guess = "2.0.5" [profile.release] codegen-units = 1 diff --git a/sync-server/build.rs b/sync-server/build.rs index d5068697..41c6cbba 100644 --- a/sync-server/build.rs +++ b/sync-server/build.rs @@ -1,5 +1,77 @@ -// generated by `sqlx migrate build-script` +use std::path::PathBuf; +use std::process::Command; + fn main() { - // trigger recompilation when a new migration is added - println!("cargo:rerun-if-changed=migrations"); + println!("cargo:rerun-if-changed=../docs"); + + let docs_dir = PathBuf::from("../docs"); + let dist_dir = docs_dir.join(".vitepress").join("dist"); + + // Check if npm is available + let npm_check = if cfg!(target_os = "windows") { + Command::new("cmd") + .args(["/C", "npm", "--version"]) + .output() + } else { + Command::new("npm").arg("--version").output() + }; + + match npm_check { + Ok(output) if output.status.success() => { + println!("cargo:warning=Building VitePress documentation..."); + + // Install dependencies if node_modules doesn't exist + if !docs_dir.join("node_modules").exists() { + println!("cargo:warning=Installing npm dependencies..."); + let npm_install = if cfg!(target_os = "windows") { + Command::new("cmd") + .args(["/C", "npm", "install"]) + .current_dir(&docs_dir) + .status() + } else { + Command::new("npm") + .arg("install") + .current_dir(&docs_dir) + .status() + }; + + if let Err(e) = npm_install { + println!("cargo:warning=Failed to install npm dependencies: {e}"); + println!("cargo:warning=Docs will not be embedded in the binary"); + return; + } + } + + // Build the VitePress docs + let build_result = if cfg!(target_os = "windows") { + Command::new("cmd") + .args(["/C", "npm", "run", "build"]) + .current_dir(&docs_dir) + .status() + } else { + Command::new("npm") + .args(["run", "build"]) + .current_dir(&docs_dir) + .status() + }; + + match build_result { + Ok(status) if status.success() => { + println!("cargo:warning=VitePress docs built successfully at {dist_dir:?}"); + } + Ok(status) => { + println!("cargo:warning=VitePress build failed with status: {status}"); + println!("cargo:warning=Docs will not be embedded in the binary"); + } + Err(e) => { + println!("cargo:warning=Failed to build VitePress docs: {e}"); + println!("cargo:warning=Docs will not be embedded in the binary"); + } + } + } + _ => { + println!("cargo:warning=npm not found - skipping VitePress build"); + println!("cargo:warning=Docs will not be embedded in the binary"); + } + } } diff --git a/sync-server/src/server.rs b/sync-server/src/server.rs index 01b09cf6..7adc5fe3 100644 --- a/sync-server/src/server.rs +++ b/sync-server/src/server.rs @@ -6,10 +6,10 @@ mod fetch_document_version; mod fetch_document_version_content; mod fetch_latest_document_version; mod fetch_latest_documents; -mod index; mod ping; mod requests; mod responses; +mod static_files; mod update_document; mod websocket; @@ -53,9 +53,10 @@ pub async fn create_server(config: Config) -> Result<()> { let app = Router::new() .nest("/", get_authed_routes(app_state.clone())) - .route("/", get(index::index)) + .route("/", get(static_files::serve_index)) .route("/vaults/:vault_id/ping", get(ping::ping)) .route("/vaults/:vault_id/ws", get(websocket::websocket_handler)) + .route("/*path", get(static_files::serve_static_file)) .layer(DefaultBodyLimit::disable()) .layer(RequestBodyLimitLayer::new( app_state.config.server.max_body_size_mb * 1024 * 1024, diff --git a/sync-server/src/server/index.rs b/sync-server/src/server/index.rs deleted file mode 100644 index 64b053f7..00000000 --- a/sync-server/src/server/index.rs +++ /dev/null @@ -1,7 +0,0 @@ -use axum::response::{Html, IntoResponse}; - -pub async fn index() -> impl IntoResponse { - const HTML_CONTENT: &str = include_str!("./assets/index.html"); - let html_content = HTML_CONTENT; - Html(html_content) -} diff --git a/sync-server/src/server/static_files.rs b/sync-server/src/server/static_files.rs new file mode 100644 index 00000000..eaa31cb9 --- /dev/null +++ b/sync-server/src/server/static_files.rs @@ -0,0 +1,55 @@ +use axum::{ + extract::Path, + http::{StatusCode, header}, + response::{Html, IntoResponse, Response}, +}; +use rust_embed::Embed; + +#[derive(Embed)] +#[folder = "../docs/.vitepress/dist"] +pub struct DocsAssets; + +pub async fn serve_static_file(Path(path): Path) -> Response { + let path = if path.is_empty() { "index.html" } else { &path }; + + match DocsAssets::get(path) { + Some(content) => { + let mime_type = mime_guess::from_path(path).first_or_octet_stream(); + let body = content.data.into_owned(); + + Response::builder() + .status(StatusCode::OK) + .header(header::CONTENT_TYPE, mime_type.as_ref()) + .header(header::CACHE_CONTROL, "public, max-age=3600") + .body(body.into()) + .unwrap() + } + None => { + // For SPA routing, if file not found, try serving index.html + match DocsAssets::get("index.html") { + Some(content) => { + Html(String::from_utf8_lossy(&content.data).to_string()).into_response() + } + None => (StatusCode::NOT_FOUND, "Documentation not found").into_response(), + } + } + } +} + +pub async fn serve_index() -> Response { + match DocsAssets::get("index.html") { + Some(content) => Html(String::from_utf8_lossy(&content.data).to_string()) + .into_response(), + None => { + Html(r" + + VaultLink Server + +

VaultLink Sync Server

+

Documentation not available. The server was compiled without embedded docs.

+ + + ").into_response() + } + } +}