alot of progress
This commit is contained in:
310
Cargo.lock
generated
310
Cargo.lock
generated
@@ -46,6 +46,7 @@ dependencies = [
|
|||||||
"tower",
|
"tower",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -64,6 +65,30 @@ dependencies = [
|
|||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "axum-extra"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9963ff19f40c6102c76756ef0a46004c0d58957d87259fc9208ff8441c12ab96"
|
||||||
|
dependencies = [
|
||||||
|
"axum",
|
||||||
|
"axum-core",
|
||||||
|
"bytes",
|
||||||
|
"cookie",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"http-body-util",
|
||||||
|
"mime",
|
||||||
|
"pin-project-lite",
|
||||||
|
"rustversion",
|
||||||
|
"serde_core",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -77,6 +102,12 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.19.0"
|
version = "3.19.0"
|
||||||
@@ -106,6 +137,26 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cookie"
|
||||||
|
version = "0.18.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
|
||||||
|
dependencies = [
|
||||||
|
"percent-encoding",
|
||||||
|
"time",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deranged"
|
||||||
|
version = "0.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
|
||||||
|
dependencies = [
|
||||||
|
"powerfmt",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "displaydoc"
|
name = "displaydoc"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
@@ -193,6 +244,20 @@ dependencies = [
|
|||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
|
"libc",
|
||||||
|
"r-efi",
|
||||||
|
"wasip2",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
@@ -350,12 +415,27 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.177"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litemap"
|
name = "litemap"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
|
checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchit"
|
name = "matchit"
|
||||||
version = "0.7.3"
|
version = "0.7.3"
|
||||||
@@ -407,16 +487,24 @@ name = "mis-interpreter"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"futures-util",
|
"axum-extra",
|
||||||
|
"getrandom",
|
||||||
"maud",
|
"maud",
|
||||||
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"tower-cookies",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"urlencoding",
|
"uuid",
|
||||||
"worker",
|
"worker",
|
||||||
"worker-macros",
|
"worker-macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-conv"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@@ -432,6 +520,29 @@ version = "1.21.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.2"
|
version = "2.3.2"
|
||||||
@@ -479,6 +590,21 @@ dependencies = [
|
|||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "powerfmt"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.103"
|
version = "1.0.103"
|
||||||
@@ -509,6 +635,50 @@ 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]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||||
|
dependencies = [
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.22"
|
version = "1.0.22"
|
||||||
@@ -521,6 +691,12 @@ version = "1.0.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.228"
|
version = "1.0.228"
|
||||||
@@ -598,6 +774,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1_smol"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.11"
|
version = "0.4.11"
|
||||||
@@ -644,6 +826,37 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.3.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
|
||||||
|
dependencies = [
|
||||||
|
"deranged",
|
||||||
|
"itoa",
|
||||||
|
"num-conv",
|
||||||
|
"powerfmt",
|
||||||
|
"serde",
|
||||||
|
"time-core",
|
||||||
|
"time-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-core"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-macros"
|
||||||
|
version = "0.2.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
|
||||||
|
dependencies = [
|
||||||
|
"num-conv",
|
||||||
|
"time-core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinystr"
|
name = "tinystr"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
@@ -677,6 +890,22 @@ dependencies = [
|
|||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-cookies"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "151b5a3e3c45df17466454bb74e9ecedecc955269bdedbf4d150dfa393b55a36"
|
||||||
|
dependencies = [
|
||||||
|
"axum-core",
|
||||||
|
"cookie",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"parking_lot",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-layer"
|
name = "tower-layer"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@@ -689,6 +918,22 @@ version = "0.3.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing"
|
||||||
|
version = "0.1.41"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
|
||||||
|
dependencies = [
|
||||||
|
"pin-project-lite",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-core"
|
||||||
|
version = "0.1.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.20"
|
version = "1.0.20"
|
||||||
@@ -707,24 +952,39 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "urlencoding"
|
|
||||||
version = "2.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8_iter"
|
name = "utf8_iter"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "1.18.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"js-sys",
|
||||||
|
"sha1_smol",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
|
[[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 = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.105"
|
version = "0.2.105"
|
||||||
@@ -806,6 +1066,18 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.46.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "worker"
|
name = "worker"
|
||||||
version = "0.6.7"
|
version = "0.6.7"
|
||||||
@@ -895,6 +1167,26 @@ dependencies = [
|
|||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.8.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.8.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerofrom"
|
name = "zerofrom"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
|||||||
21
Cargo.toml
21
Cargo.toml
@@ -7,25 +7,22 @@ authors = ["Rivulet <cadenream@cadencoaster.com>"]
|
|||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
# (Wrangler will ignore these; fine to keep or remove)
|
|
||||||
[package.metadata.wasm-pack]
|
[package.metadata.wasm-pack]
|
||||||
target = "web"
|
target = "web"
|
||||||
out-dir = "build"
|
out-dir = "build"
|
||||||
out-name = "index"
|
out-name = "index"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Cloudflare Workers (HTTP + Axum adapter)
|
worker = { version = "0.6", features = ['http', 'axum'] }
|
||||||
worker = { version = "0.6", features = ["http", "axum"] }
|
worker-macros = { version = "0.6", features = ['http'] }
|
||||||
worker-macros = { version = "0.6", features = ["http"] }
|
|
||||||
|
|
||||||
# Axum *without* tokio/hyper; we don't use its WS, so don't enable it.
|
|
||||||
axum = { version = "0.8", default-features = false, features = ["form", "macros"] }
|
axum = { version = "0.8", default-features = false, features = ["form", "macros"] }
|
||||||
|
|
||||||
tower-service = "0.3.3"
|
tower-service = "0.3.3"
|
||||||
|
|
||||||
maud = { version = "0.27.0", default-features = false }
|
maud = { version = "0.27.0", default-features = false }
|
||||||
|
rand = { version = "0.9.2",default-features = false, features = ["thread_rng"] }
|
||||||
|
serde = { version = "1.0.228", default-features = false, features = ["derive"] }
|
||||||
|
tower-cookies = "0.11.0"
|
||||||
|
axum-extra = { version = "0.10.3", features = ["cookie"] }
|
||||||
|
uuid = { version = "1.18", features = ["v4", "v7", "v5", "js"] }
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
|
getrandom = { version = "0.3", features = ["wasm_js"] }
|
||||||
|
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
|
||||||
serde_json = "1.0.145"
|
|
||||||
urlencoding = "2.1.3"
|
|
||||||
futures-util = "0.3.31"
|
|
||||||
|
|||||||
469
src/lib.rs
469
src/lib.rs
@@ -1,339 +1,214 @@
|
|||||||
use axum::{
|
use axum::http::{status, HeaderMap, HeaderValue, StatusCode};
|
||||||
body::{to_bytes, Body},
|
use axum::response::{Html, Redirect };
|
||||||
http::{Response as AxumResponse, StatusCode},
|
use axum::routing::post;
|
||||||
response::Html,
|
use axum::{routing::get, Extension, Form, Router};
|
||||||
routing::{get, post},
|
use axum::http::header::SET_COOKIE;
|
||||||
Form, Router,
|
use axum_extra::extract::cookie::Cookie;
|
||||||
};
|
use axum_extra::extract::CookieJar;
|
||||||
use futures_util::StreamExt;
|
use maud::html;
|
||||||
use maud::{html, Markup};
|
use tower_cookies::{CookieManagerLayer, Cookies};
|
||||||
use serde::Deserialize;
|
|
||||||
use tower_service::Service;
|
use tower_service::Service;
|
||||||
|
use uuid::Uuid;
|
||||||
use worker::*;
|
use worker::*;
|
||||||
|
use worker::wasm_bindgen_futures::spawn_local;
|
||||||
|
|
||||||
/* ===================== Router ===================== */
|
#[durable_object]
|
||||||
|
pub struct Room {
|
||||||
|
state: State,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_id() -> String {
|
||||||
|
Uuid::now_v7().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_jar(req: &Request) -> CookieJar {
|
||||||
|
let mut jar = CookieJar::new();
|
||||||
|
if let Ok(Some(header)) = req.headers().get("Cookie") {
|
||||||
|
for c in Cookie::split_parse(header) {
|
||||||
|
if let Ok(c) = c {
|
||||||
|
jar = jar.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jar
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DurableObject for Room {
|
||||||
|
fn new(state: State, env: Env) -> Self {
|
||||||
|
Self { state }
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch(&self, req: Request) -> Result<Response> {
|
||||||
|
let cookie = load_jar(&req);
|
||||||
|
let url = req.url()?;
|
||||||
|
match (req.method(), url.path()) {
|
||||||
|
(Method::Get, "/ws") => {
|
||||||
|
|
||||||
|
let pair = WebSocketPair::new()?;
|
||||||
|
let server = pair.server;
|
||||||
|
let client = pair.client;
|
||||||
|
|
||||||
|
server.accept()?;
|
||||||
|
|
||||||
|
Response::from_websocket(client)
|
||||||
|
}
|
||||||
|
(Method::Post, "/setname") => {
|
||||||
|
let name = req.headers().get("Name").unwrap_or(None);
|
||||||
|
if name.is_some() {
|
||||||
|
self.state.storage().put("name", name.unwrap()).await.expect("failed to write to storage");
|
||||||
|
Response::ok("Ok")
|
||||||
|
} else {
|
||||||
|
Response::error("No name provided", StatusCode::BAD_REQUEST.as_u16())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn router() -> Router {
|
fn router() -> Router {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/", get(root))
|
.route("/", get(root))
|
||||||
.route("/create", post(create_game))
|
.route("/create", post(create))
|
||||||
// /ws is handled in fetch() using CF WebSocketPair.
|
.route("/lobby", get(lobby))
|
||||||
|
}
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Params {
|
||||||
|
env: Env,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================== Cloudflare entry ===================== */
|
|
||||||
|
|
||||||
#[event(fetch)]
|
#[event(fetch)]
|
||||||
async fn fetch(req: HttpRequest, _env: Env, _ctx: Context) -> Result<Response> {
|
async fn fetch(
|
||||||
// Intercept WebSocket before handing off to Axum
|
mut req: HttpRequest,
|
||||||
let is_ws = req
|
env: Env,
|
||||||
.headers()
|
_ctx: Context,
|
||||||
.get("Upgrade")
|
) -> Result<axum::http::Response<axum::body::Body>> {
|
||||||
.and_then(|v| v.to_str().ok())
|
|
||||||
.map(|v| v.eq_ignore_ascii_case("websocket"))
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
if req.uri().path() == "/ws" && is_ws {
|
let url = req.uri();
|
||||||
return handle_ws_upgrade(req).await;
|
let path = url.path();
|
||||||
|
|
||||||
|
// Expect: /ws/{name}
|
||||||
|
if path == "/ws" {
|
||||||
|
let jar = load_jar(&req.try_into()?);
|
||||||
|
let name = jar.get("game_id").expect("failed to get game_id").to_string();
|
||||||
|
|
||||||
|
// Resolve the DO instance deterministically by name
|
||||||
|
let ns = env.durable_object("ROOM")?; // binding in wrangler.toml
|
||||||
|
let id = ns.id_from_name(&*name)?;
|
||||||
|
let stub = id.get_stub()?;
|
||||||
|
|
||||||
|
return Ok(stub.fetch_with_request(Request::new("http://do/ws", Method::Get)?).await.expect("failed to connect").try_into()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise hand off to Axum and adapt Axum -> Worker Response
|
|
||||||
let axum_resp: AxumResponse<Body> = router().call(req).await?;
|
req.extensions_mut().insert( Params{ env});
|
||||||
axum_to_worker(axum_resp).await
|
Ok(router().call(req).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert an Axum response into a worker::Response */
|
#[derive(serde::Deserialize, Debug, Clone)]
|
||||||
async fn axum_to_worker(ax: AxumResponse<Body>) -> Result<Response> {
|
pub struct CreateGameForm {
|
||||||
let (parts, body) = ax.into_parts();
|
game_name: Option<String>, // <- String, not &str
|
||||||
let bytes = to_bytes(body, usize::MAX).await.unwrap_or_default();
|
password: Option<String>,
|
||||||
|
player_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
let mut resp = Response::from_bytes(bytes.to_vec())?;
|
#[axum::debug_handler]
|
||||||
resp = resp.with_status(parts.status.as_u16());
|
pub async fn create(Extension(params): Extension<Params>, mut jar: CookieJar, Form(form): Form<CreateGameForm>) -> (CookieJar, Redirect) {
|
||||||
|
let id = gen_id();
|
||||||
for (name, value) in parts.headers.iter() {
|
jar = jar.add(Cookie::new("game_id", id.clone()));
|
||||||
if let Ok(val) = value.to_str() {
|
jar = jar.add(Cookie::new("player_name", form.player_name.clone()));
|
||||||
resp.headers_mut().set(name.as_str(), val)?; // <- note: no ? after headers_mut()
|
if !form.game_name.clone().unwrap_or("".to_string()).is_empty() {
|
||||||
}
|
jar = jar.add(Cookie::new("game_name", form.game_name.as_ref().unwrap_or(&"".to_string()).clone()));
|
||||||
}
|
}
|
||||||
Ok(resp)
|
if !form.password.clone().unwrap_or("".to_string()).is_empty() {
|
||||||
}
|
jar = jar.add(Cookie::new("password", form.password.as_ref().unwrap_or(&"".to_string()).clone()));
|
||||||
|
}
|
||||||
/* ===================== Pages ===================== */
|
let ns = params.env.durable_object("ROOM").unwrap();
|
||||||
|
let id = ns.id_from_name(&*format!("room-{}",id)).expect("Failed to find game_name");
|
||||||
/// GET /
|
let stub = id.get_stub().expect("Failed to find stub");
|
||||||
pub async fn root() -> Html<String> {
|
let req = Request::new("http://do/setname", Method::Post).unwrap();
|
||||||
// If you want to read cookies here, switch to a custom Response and pass headers in via extractors.
|
req.headers().set("Name", &*form.game_name.clone().unwrap_or("".to_string())).expect("Failed to set header");
|
||||||
let page = render_page(None);
|
let name = form.game_name.clone().unwrap_or("".to_string());
|
||||||
Html::from(page)
|
spawn_local(async move {
|
||||||
}
|
if let Err(e) = stub.fetch_with_request(req).await {
|
||||||
|
console_error!("failed to set name: {}",e)
|
||||||
/// POST /create (classic PRG with cookie flash)
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct CreateForm {
|
|
||||||
game_name: Option<String>,
|
|
||||||
password: Option<String>,
|
|
||||||
player_name: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn create_game(Form(form): Form<CreateForm>) -> AxumResponse<Body> {
|
|
||||||
let msg = flash_msg(&form);
|
|
||||||
AxumResponse::builder()
|
|
||||||
.status(StatusCode::SEE_OTHER)
|
|
||||||
.header("Location", "/")
|
|
||||||
.header(
|
|
||||||
"Set-Cookie",
|
|
||||||
format!(
|
|
||||||
"flash={}; Path=/; Max-Age=30; HttpOnly; SameSite=Lax",
|
|
||||||
urlencoding::encode(&msg)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.body(Body::empty())
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===================== WebSocket (HTMX ws-send) ===================== */
|
|
||||||
|
|
||||||
async fn handle_ws_upgrade(_req: HttpRequest) -> Result<Response> {
|
|
||||||
// Create the CF WebSocketPair at the worker layer
|
|
||||||
let pair = WebSocketPair::new()?;
|
|
||||||
let server = pair.server;
|
|
||||||
let client = pair.client;
|
|
||||||
|
|
||||||
server.accept()?;
|
|
||||||
|
|
||||||
// Spawn a local task to read messages and push OOB HTML back.
|
|
||||||
wasm_bindgen_futures::spawn_local(async move {
|
|
||||||
// Create the borrow-bound event stream *inside* the task and keep the clone alive.
|
|
||||||
let server_clone = server.clone();
|
|
||||||
let mut events = match server_clone.events() {
|
|
||||||
Ok(e) => e,
|
|
||||||
Err(_) => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
while let Some(Ok(evt)) = events.next().await {
|
|
||||||
if let WebsocketEvent::Message(m) = evt {
|
|
||||||
if let Some(txt) = m.text() {
|
|
||||||
if let Ok(parsed) = serde_json::from_str::<CreateForm>(&*txt) {
|
|
||||||
let msg = flash_msg(&parsed);
|
|
||||||
let oob = render_flash_oob(&msg);
|
|
||||||
let _ = server_clone.send_with_str(oob);
|
|
||||||
} else {
|
|
||||||
let _ = server_clone.send_with_str(render_log_oob("Unrecognized message"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Return the upgrade response (must be worker::Response)
|
console_log!("{:?} id:{}", form, id);
|
||||||
Response::from_websocket(client)
|
(jar, Redirect::to("/lobby"))
|
||||||
}
|
}
|
||||||
|
pub async fn root() -> Html<String> {
|
||||||
/* ===================== View / HTML ===================== */
|
Html::from(html! {
|
||||||
|
|
||||||
fn render_page(flash: Option<&str>) -> String {
|
|
||||||
(html! {
|
|
||||||
(maud::DOCTYPE)
|
(maud::DOCTYPE)
|
||||||
html lang="en" {
|
html lang="en" {
|
||||||
head {
|
head {
|
||||||
meta charset="utf-8";
|
meta charset="utf-8";
|
||||||
meta name="viewport" content="width=device-width, initial-scale=1";
|
meta name="viewport" content="width=device-width, initial-scale=1";
|
||||||
title { "Mis-Interpreter" }
|
title { "Mis-Interpreter" }
|
||||||
|
|
||||||
// HTMX + WS Extension
|
|
||||||
script src="https://unpkg.com/htmx.org@2.0.4" {}
|
|
||||||
script src="https://unpkg.com/htmx-ext-ws@2.0.3/ws.js" {}
|
|
||||||
|
|
||||||
style { (PASTEL_CSS) }
|
style { (PASTEL_CSS) }
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
main class="shell" {
|
main class="shell" {
|
||||||
section class="card cartoon" {
|
section class="card cartoon" {
|
||||||
h1 class="title" { "Mis-Interpreter" }
|
h1 class="title" {
|
||||||
p class="subtitle" { "Create a game?" }
|
"Mis-Interpreter"
|
||||||
|
|
||||||
// Flash target
|
|
||||||
div id="flash" {
|
|
||||||
@if let Some(msg) = flash {
|
|
||||||
(render_flash_inline(msg))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
p class="subtitle" {
|
||||||
// Live form using htmx WebSocket
|
"Create a game?"
|
||||||
div hx-ext="ws" ws-connect="/ws" {
|
}
|
||||||
form id="create-form" class="form" ws-send {
|
form method="post" action="/create" class="form" {
|
||||||
label class="sr" for="game_name" { "Game Name" }
|
label class="sr" for="game_name" {
|
||||||
input id="game_name" type="text" name="game_name"
|
"Game Name"
|
||||||
placeholder="Game Name (Optional)" class="input";
|
}
|
||||||
|
input id="game_name" type="text" name="game_name" placeholder="Game Name (Optional)" class="input";
|
||||||
label class="sr" for="password" { "Password" }
|
label class="sr" for="password" {
|
||||||
input id="password" type="password" name="password"
|
"Password"
|
||||||
placeholder="Password (Optional)" class="input";
|
}
|
||||||
|
input id="password" type="password" name="password" placeholder="Password (Optional)" class="input"; label class="sr" for="player_name" {
|
||||||
label class="sr" for="player_name" { "Player Name" }
|
"Player Name"
|
||||||
input id="player_name" type="text" name="player_name"
|
}
|
||||||
value="John Wick" class="input";
|
input id="player_name" type="text" name="player_name" value="John Wick" class="input"; button type="submit" class="btn" {
|
||||||
|
"Create"
|
||||||
button type="submit" class="btn" { "Create (Live)" }
|
|
||||||
}
|
}
|
||||||
div id="ws-log" class="wslog" {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).into_string()
|
}.into_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_flash_inline(msg: &str) -> Markup {
|
pub async fn lobby(jar: CookieJar) -> Html<String> {
|
||||||
html! { div class="flash cartoon" { (escape(msg)) } }
|
let title = jar.get("game_name").and_then(|v| Some(v.value())).unwrap_or("Lobby");
|
||||||
|
Html::from(html! {
|
||||||
|
(maud::DOCTYPE)
|
||||||
|
html lang="en" {
|
||||||
|
head {
|
||||||
|
meta charset="utf-8";
|
||||||
|
meta name="viewport" content="width=device-width, initial-scale=1";
|
||||||
|
script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js" integrity="sha384-/TgkGk7p307TH7EXJDuUlgG3Ce1UVolAOFopFekQkkXihi5u/6OCvVKyz1W+idaz" crossorigin="anonymous" {}
|
||||||
|
script src="https://unpkg.com/htmx.org@1.9.12/dist/ext/ws.js" {}
|
||||||
|
title { "Mis-Interpreter - "(title) }
|
||||||
|
style { (PASTEL_CSS) }
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
main class="shell" {
|
||||||
|
section class="card cartoon" {
|
||||||
|
h1 class="title" {
|
||||||
|
(title)
|
||||||
|
}
|
||||||
|
hr;
|
||||||
|
p class="subtitle" {
|
||||||
|
"Player List"
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.into_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_flash_oob(msg: &str) -> String {
|
const PASTEL_CSS: &str = r#" /* ===== Pastel Blues, Cartoon Borders ===== */ :root{ /* palette */ --sky-50:#eff6ff; --sky-100:#dbeafe; --sky-200:#bfdbfe; --sky-300:#93c5fd; --sky-400:#60a5fa; --sky-500:#3b82f6; --indigo-600:#4f46e5; --teal-300:#99f6e4; --bg-top: color-mix(in oklab, var(--sky-100) 70%, white); --bg-bot: color-mix(in oklab, var(--teal-300) 35%, white); --card: #f2f7ff; --ink: #0b1220; --muted:#44506a; /* cartoon outlines */ --outline: #133a84; /* deep blue stroke */ --shadow: #0e2250; /* offset shadow for sticker look */ --ring: var(--sky-400); --field-a: #e9f2ff; --field-b: #e6fffb; --btn-a: #a5b4ff; /* indigo pastel */ --btn-b: #7dd3fc; /* sky pastel */ --flash-bg:#c4f1f9; /* cyan-200 */ --flash-border:#0891b2; } *{box-sizing:border-box} html,body{height:100%} body{ margin:0; font:17px/1.55 ui-sans-serif, system-ui, -apple-system, Segoe UI, Inter, Roboto, Arial; color:var(--ink); background: radial-gradient(1000px 700px at 15% -10%, var(--sky-200) 0%, transparent 60%), radial-gradient(1100px 800px at 110% 0%, var(--teal-300) 0%, transparent 60%), linear-gradient(180deg, var(--bg-top), var(--bg-bot)); } /* ——— cartoon helpers ——— */ .cartoon{ border:4px solid var(--outline); box-shadow: 8px 8px 0 var(--shadow); border-radius: 26px; } /* layout */ .shell{min-height:100%; display:grid; place-items:center; padding:3rem 1rem} .card{ width:min(740px, 94vw); background: var(--card); padding:3rem 2.5rem; } .card.cartoon{} /* (keep class for specificity) */ .title{ text-align:center; margin:0 0 .5rem; font-weight:900; letter-spacing:.3px; font-size: clamp(2.1rem, 3.4vw + 1rem, 3.4rem); /* shiny blue gradient text */ background: linear-gradient(90deg, var(--sky-500), var(--indigo-600)); -webkit-background-clip: text; background-clip: text; color: transparent; text-shadow: 0 2px 0 #ffffff66; } .subtitle{ text-align:center; color:var(--muted); margin:0 0 2rem; font-weight:700 } .flash{ background: var(--flash-bg); border:4px solid var(--flash-border); color:#0c4a6e; padding:.85rem 1rem; border-radius:16px; margin:0 0 1.25rem; box-shadow: 6px 6px 0 var(--shadow); } /* form */ .form{ display:grid; grid-template-columns:1fr auto; gap:16px 16px; align-items:center } .input{ width:100%; padding:1rem 1.1rem; border:4px solid var(--outline); border-radius:16px; background: linear-gradient(0deg, #ffffff, #ffffff) padding-box, radial-gradient(120% 120% at 0% 0%, var(--field-a) 0%, var(--field-b) 100%) border-box; color:var(--ink); box-shadow: 4px 4px 0 var(--shadow); transition: transform .06s ease, box-shadow .15s ease, border-color .15s ease; } .input::placeholder{color:#6b7280} .input:focus{ outline:none; transform: translateY(-1px); border-color: var(--ring); box-shadow: 6px 6px 0 var(--shadow), 0 0 0 6px color-mix(in oklab, var(--ring) 40%, white); } /* button: chunky pill with dual-tone blue */ .btn{ padding:1rem 1.35rem; font-weight:900; border:4px solid var(--outline); border-radius:999px; color:#06223a; background: linear-gradient(180deg, color-mix(in oklab, var(--btn-b) 75%, white), color-mix(in oklab, var(--btn-a) 85%, white)); cursor:pointer; box-shadow: 6px 6px 0 var(--shadow); transition: transform .07s ease, filter .15s ease, box-shadow .15s ease; } .btn:hover{ filter:brightness(1.06) saturate(1.05) } .btn:active{ transform: translateY(2px); box-shadow: 4px 4px 0 var(--shadow) } /* accessibility */ .sr{ position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0 } /* responsive */ @media (max-width: 560px){ .form{ grid-template-columns: 1fr } .btn{ width:100% } } "#;
|
||||||
format!(
|
|
||||||
r#"<div id="flash" hx-swap-oob="true"><div class="flash cartoon">{}</div></div>"#,
|
|
||||||
escape(msg)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_log_oob(text: &str) -> String {
|
|
||||||
format!(r#"<div id="ws-log" hx-swap-oob="true">{}</div>"#, escape(text))
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===================== Utilities ===================== */
|
|
||||||
|
|
||||||
fn flash_msg(form: &CreateForm) -> String {
|
|
||||||
let game = form.game_name.as_deref().unwrap_or("Untitled");
|
|
||||||
let player = form.player_name.as_deref().unwrap_or("Anonymous");
|
|
||||||
let priv_tag = if form.password.as_deref().unwrap_or("").is_empty() { "" } else { " (private)" };
|
|
||||||
format!("Created game '{}' for '{}'{priv_tag}", escape(game), escape(player))
|
|
||||||
}
|
|
||||||
|
|
||||||
// minimal safe escaping for text nodes
|
|
||||||
fn escape(s: &str) -> String {
|
|
||||||
s.replace('&', "&").replace('<', "<").replace('>', ">")
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===================== Theme ===================== */
|
|
||||||
|
|
||||||
const PASTEL_CSS: &str = r#"
|
|
||||||
/* ===== Pastel Blues, Cartoon Borders ===== */
|
|
||||||
:root{
|
|
||||||
/* palette */
|
|
||||||
--sky-50:#eff6ff; --sky-100:#dbeafe; --sky-200:#bfdbfe; --sky-300:#93c5fd;
|
|
||||||
--sky-400:#60a5fa; --sky-500:#3b82f6; --indigo-600:#4f46e5; --teal-300:#99f6e4;
|
|
||||||
|
|
||||||
--bg-top: color-mix(in oklab, var(--sky-100) 70%, white);
|
|
||||||
--bg-bot: color-mix(in oklab, var(--teal-300) 35%, white);
|
|
||||||
|
|
||||||
--card: #f2f7ff;
|
|
||||||
--ink: #0b1220;
|
|
||||||
--muted:#44506a;
|
|
||||||
|
|
||||||
/* cartoon outlines */
|
|
||||||
--outline: #133a84; /* deep blue stroke */
|
|
||||||
--shadow: #0e2250; /* offset shadow for sticker look */
|
|
||||||
|
|
||||||
--ring: var(--sky-400);
|
|
||||||
--field-a: #e9f2ff;
|
|
||||||
--field-b: #e6fffb;
|
|
||||||
|
|
||||||
--btn-a: #a5b4ff; /* indigo pastel */
|
|
||||||
--btn-b: #7dd3fc; /* sky pastel */
|
|
||||||
|
|
||||||
--flash-bg:#c4f1f9; /* cyan-200 */
|
|
||||||
--flash-border:#0891b2;
|
|
||||||
}
|
|
||||||
|
|
||||||
*{box-sizing:border-box}
|
|
||||||
html,body{height:100%}
|
|
||||||
body{
|
|
||||||
margin:0;
|
|
||||||
font:17px/1.55 ui-sans-serif, system-ui, -apple-system, Segoe UI, Inter, Roboto, Arial;
|
|
||||||
color:var(--ink);
|
|
||||||
background:
|
|
||||||
radial-gradient(1000px 700px at 15% -10%, var(--sky-200) 0%, transparent 60%),
|
|
||||||
radial-gradient(1100px 800px at 110% 0%, var(--teal-300) 0%, transparent 60%),
|
|
||||||
linear-gradient(180deg, var(--bg-top), var(--bg-bot));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ——— cartoon helpers ——— */
|
|
||||||
.cartoon{
|
|
||||||
border:4px solid var(--outline);
|
|
||||||
box-shadow: 8px 8px 0 var(--shadow);
|
|
||||||
border-radius: 26px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* layout */
|
|
||||||
.shell{min-height:100%; display:grid; place-items:center; padding:3rem 1rem}
|
|
||||||
.card{
|
|
||||||
width:min(740px, 94vw);
|
|
||||||
background: var(--card);
|
|
||||||
padding:3rem 2.5rem;
|
|
||||||
}
|
|
||||||
.card.cartoon{} /* (keep class for specificity) */
|
|
||||||
|
|
||||||
.title{
|
|
||||||
text-align:center; margin:0 0 .5rem; font-weight:900; letter-spacing:.3px;
|
|
||||||
font-size: clamp(2.1rem, 3.4vw + 1rem, 3.4rem);
|
|
||||||
/* shiny blue gradient text */
|
|
||||||
background: linear-gradient(90deg, var(--sky-500), var(--indigo-600));
|
|
||||||
-webkit-background-clip: text; background-clip: text; color: transparent;
|
|
||||||
text-shadow: 0 2px 0 #ffffff66;
|
|
||||||
}
|
|
||||||
.subtitle{ text-align:center; color:var(--muted); margin:0 0 2rem; font-weight:700 }
|
|
||||||
|
|
||||||
.flash{
|
|
||||||
background: var(--flash-bg);
|
|
||||||
border:4px solid var(--flash-border);
|
|
||||||
color:#0c4a6e;
|
|
||||||
padding:.85rem 1rem; border-radius:16px; margin:0 0 1.25rem;
|
|
||||||
box-shadow: 6px 6px 0 var(--shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* form */
|
|
||||||
.form{ display:grid; grid-template-columns:1fr auto; gap:16px 16px; align-items:center }
|
|
||||||
.input{
|
|
||||||
width:100%;
|
|
||||||
padding:1rem 1.1rem;
|
|
||||||
border:4px solid var(--outline);
|
|
||||||
border-radius:16px;
|
|
||||||
background:
|
|
||||||
linear-gradient(0deg, #ffffff, #ffffff) padding-box,
|
|
||||||
radial-gradient(120% 120% at 0% 0%, var(--field-a) 0%, var(--field-b) 100%) border-box;
|
|
||||||
color:var(--ink);
|
|
||||||
box-shadow: 4px 4px 0 var(--shadow);
|
|
||||||
transition: transform .06s ease, box-shadow .15s ease, border-color .15s ease;
|
|
||||||
}
|
|
||||||
.input::placeholder{color:#6b7280}
|
|
||||||
.input:focus{
|
|
||||||
outline:none; transform: translateY(-1px);
|
|
||||||
border-color: var(--ring);
|
|
||||||
box-shadow: 6px 6px 0 var(--shadow), 0 0 0 6px color-mix(in oklab, var(--ring) 40%, white);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* button: chunky pill with dual-tone blue */
|
|
||||||
.btn{
|
|
||||||
padding:1rem 1.35rem;
|
|
||||||
font-weight:900;
|
|
||||||
border:4px solid var(--outline);
|
|
||||||
border-radius:999px;
|
|
||||||
color:#06223a;
|
|
||||||
background: linear-gradient(180deg,
|
|
||||||
color-mix(in oklab, var(--btn-b) 75%, white),
|
|
||||||
color-mix(in oklab, var(--btn-a) 85%, white));
|
|
||||||
cursor:pointer;
|
|
||||||
box-shadow: 6px 6px 0 var(--shadow);
|
|
||||||
transition: transform .07s ease, filter .15s ease, box-shadow .15s ease;
|
|
||||||
}
|
|
||||||
.btn:hover{ filter:brightness(1.06) saturate(1.05) }
|
|
||||||
.btn:active{ transform: translateY(2px); box-shadow: 4px 4px 0 var(--shadow) }
|
|
||||||
|
|
||||||
/* accessibility */
|
|
||||||
.sr{ position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0 }
|
|
||||||
|
|
||||||
/* responsive */
|
|
||||||
@media (max-width: 560px){
|
|
||||||
.form{ grid-template-columns: 1fr }
|
|
||||||
.btn{ width:100% }
|
|
||||||
}
|
|
||||||
"#;
|
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
name = "mis-interpreter"
|
name = "mis-interpreter"
|
||||||
workers_dev = true
|
|
||||||
compatibility_date = "2025-10-27"
|
|
||||||
main = "build/worker/shim.mjs"
|
main = "build/worker/shim.mjs"
|
||||||
|
compatibility_date = "2024-11-06"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
command = "cargo install -q worker-build && worker-build --release" # required
|
command = "cargo install -q worker-build && worker-build --release"
|
||||||
|
|
||||||
|
[durable_objects]
|
||||||
|
bindings = [
|
||||||
|
{ name = "ROOM", class_name = "Room" }
|
||||||
|
]
|
||||||
|
|
||||||
|
[[migrations]]
|
||||||
|
tag = "v1"
|
||||||
|
new_classes = ["Room"]
|
||||||
|
|||||||
Reference in New Issue
Block a user