cli login works and hello-world spacetime module
This commit is contained in:
310
Cargo.lock
generated
310
Cargo.lock
generated
@@ -144,6 +144,15 @@ version = "1.0.102"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "approx"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ar_archive_writer"
|
name = "ar_archive_writer"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@@ -153,6 +162,18 @@ dependencies = [
|
|||||||
"object",
|
"object",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayref"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ascii"
|
name = "ascii"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -612,6 +633,20 @@ dependencies = [
|
|||||||
"wyz",
|
"wyz",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blake3"
|
||||||
|
version = "1.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d"
|
||||||
|
dependencies = [
|
||||||
|
"arrayref",
|
||||||
|
"arrayvec",
|
||||||
|
"cc",
|
||||||
|
"cfg-if 1.0.4",
|
||||||
|
"constant_time_eq",
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block"
|
name = "block"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@@ -664,6 +699,12 @@ dependencies = [
|
|||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.25.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@@ -1094,6 +1135,12 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "constant_time_eq"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "content_disposition"
|
name = "content_disposition"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@@ -1471,6 +1518,16 @@ dependencies = [
|
|||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "decorum"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "281759d3c8a14f5c3f0c49363be56810fcd7f910422f97f2db850c2920fde5cf"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_ast"
|
name = "deno_ast"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
@@ -1895,7 +1952,7 @@ dependencies = [
|
|||||||
"dioxus-cli-config",
|
"dioxus-cli-config",
|
||||||
"http 1.4.0",
|
"http 1.4.0",
|
||||||
"infer",
|
"infer",
|
||||||
"jni",
|
"jni 0.21.1",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"ndk",
|
"ndk",
|
||||||
"ndk-context",
|
"ndk-context",
|
||||||
@@ -2018,7 +2075,7 @@ dependencies = [
|
|||||||
"generational-box 0.7.3",
|
"generational-box 0.7.3",
|
||||||
"global-hotkey",
|
"global-hotkey",
|
||||||
"infer",
|
"infer",
|
||||||
"jni",
|
"jni 0.21.1",
|
||||||
"lazy-js-bundle",
|
"lazy-js-bundle",
|
||||||
"libc",
|
"libc",
|
||||||
"muda",
|
"muda",
|
||||||
@@ -2820,6 +2877,18 @@ dependencies = [
|
|||||||
"cfg-if 1.0.4",
|
"cfg-if 1.0.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enum-as-inner"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.5.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "enumset"
|
name = "enumset"
|
||||||
version = "1.1.10"
|
version = "1.1.10"
|
||||||
@@ -2857,6 +2926,15 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ethnum"
|
||||||
|
version = "1.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca81e6b4777c89fd810c25a4be2b1bd93ea034fbe58e6a75216a34c6b82c539b"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "euclid"
|
name = "euclid"
|
||||||
version = "0.22.13"
|
version = "0.22.13"
|
||||||
@@ -3934,6 +4012,12 @@ version = "1.0.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.14.32"
|
version = "0.14.32"
|
||||||
@@ -4349,6 +4433,15 @@ dependencies = [
|
|||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
@@ -4402,19 +4495,68 @@ dependencies = [
|
|||||||
"cesu8",
|
"cesu8",
|
||||||
"cfg-if 1.0.4",
|
"cfg-if 1.0.4",
|
||||||
"combine",
|
"combine",
|
||||||
"jni-sys",
|
"jni-sys 0.3.0",
|
||||||
"log",
|
"log",
|
||||||
"thiserror 1.0.69",
|
"thiserror 1.0.69",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jni"
|
||||||
|
version = "0.22.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "295dc9997acda1562fdf8d299f56063c936443b60f078e63a5d8d3c34ef2642b"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.4",
|
||||||
|
"combine",
|
||||||
|
"jni-macros",
|
||||||
|
"jni-sys 0.4.1",
|
||||||
|
"log",
|
||||||
|
"simd_cesu8",
|
||||||
|
"thiserror 2.0.18",
|
||||||
|
"walkdir",
|
||||||
|
"windows-link 0.2.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jni-macros"
|
||||||
|
version = "0.22.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1c3d1da60c95c98847b26b9d45f4360fee718b31de746df016d9cd6de916a7ef"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustc_version",
|
||||||
|
"simd_cesu8",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jni-sys"
|
name = "jni-sys"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jni-sys"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2"
|
||||||
|
dependencies = [
|
||||||
|
"jni-sys-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jni-sys-macros"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.34"
|
version = "0.1.34"
|
||||||
@@ -4742,6 +4884,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
"dioxus",
|
||||||
"flume 0.12.0",
|
"flume 0.12.0",
|
||||||
"futures",
|
"futures",
|
||||||
"mize",
|
"mize",
|
||||||
@@ -5013,7 +5156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
|
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.11.0",
|
"bitflags 2.11.0",
|
||||||
"jni-sys",
|
"jni-sys 0.3.0",
|
||||||
"log",
|
"log",
|
||||||
"ndk-sys",
|
"ndk-sys",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
@@ -5033,7 +5176,7 @@ version = "0.6.0+11769913"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873"
|
checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jni-sys",
|
"jni-sys 0.3.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5059,6 +5202,12 @@ version = "0.1.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nohash-hasher"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "7.1.3"
|
version = "7.1.3"
|
||||||
@@ -5835,6 +5984,7 @@ dependencies = [
|
|||||||
"axum 0.8.8",
|
"axum 0.8.8",
|
||||||
"axum-extra 0.10.3",
|
"axum-extra 0.10.3",
|
||||||
"axum-oidc",
|
"axum-oidc",
|
||||||
|
"base64 0.22.1",
|
||||||
"clap",
|
"clap",
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-ssr 0.5.6",
|
"dioxus-ssr 0.5.6",
|
||||||
@@ -5855,6 +6005,7 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
"webbrowser",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5996,6 +6147,14 @@ dependencies = [
|
|||||||
"psl-types",
|
"psl-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quickstart_chat"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"spacetimedb",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quinn"
|
name = "quinn"
|
||||||
version = "0.11.9"
|
version = "0.11.9"
|
||||||
@@ -6644,7 +6803,7 @@ checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"core-foundation 0.10.1",
|
"core-foundation 0.10.1",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"jni",
|
"jni 0.21.1",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustls 0.23.37",
|
"rustls 0.23.37",
|
||||||
@@ -6807,6 +6966,12 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "second-stack"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4904c83c6e51f1b9b08bfa5a86f35a51798e8307186e6f5513852210a219c0bb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "3.7.0"
|
version = "3.7.0"
|
||||||
@@ -7155,6 +7320,22 @@ version = "0.3.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
|
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simd_cesu8"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33"
|
||||||
|
dependencies = [
|
||||||
|
"rustc_version",
|
||||||
|
"simdutf8",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simdutf8"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "siphasher"
|
name = "siphasher"
|
||||||
version = "0.3.11"
|
version = "0.3.11"
|
||||||
@@ -7293,6 +7474,113 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spacetimedb"
|
||||||
|
version = "1.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83af98280374b59796296f512f7855fd19e19240a358bb7706a54f1c4e4e7dff"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"bytemuck",
|
||||||
|
"bytes",
|
||||||
|
"derive_more 0.99.20",
|
||||||
|
"getrandom 0.2.17",
|
||||||
|
"http 1.4.0",
|
||||||
|
"log",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"scoped-tls",
|
||||||
|
"serde_json",
|
||||||
|
"spacetimedb-bindings-macro",
|
||||||
|
"spacetimedb-bindings-sys",
|
||||||
|
"spacetimedb-lib",
|
||||||
|
"spacetimedb-primitives",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spacetimedb-bindings-macro"
|
||||||
|
version = "1.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d8dbedaa26e2e59d886a19bd2b784356d8d008274046f735c9185f9943bd912"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.4.1",
|
||||||
|
"humantime",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"spacetimedb-primitives",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spacetimedb-bindings-sys"
|
||||||
|
version = "1.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a0d30e1655731b1564b7094a6213ef6c354ea920e3c04424e55ad377a1bc3e2"
|
||||||
|
dependencies = [
|
||||||
|
"spacetimedb-primitives",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spacetimedb-lib"
|
||||||
|
version = "1.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f7284d48bcfddc7c091756c6d5d3cc9a847b95778c636fdd03b9538d74a57c7"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"bitflags 2.11.0",
|
||||||
|
"blake3",
|
||||||
|
"chrono",
|
||||||
|
"derive_more 0.99.20",
|
||||||
|
"enum-as-inner",
|
||||||
|
"hex",
|
||||||
|
"itertools 0.12.1",
|
||||||
|
"log",
|
||||||
|
"spacetimedb-bindings-macro",
|
||||||
|
"spacetimedb-primitives",
|
||||||
|
"spacetimedb-sats",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spacetimedb-primitives"
|
||||||
|
version = "1.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff2dc124963dd166ecde2b4d8f0e5ed4cfd27a20d7f6bb9e84d7eff46cc520b5"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.11.0",
|
||||||
|
"either",
|
||||||
|
"enum-as-inner",
|
||||||
|
"itertools 0.12.1",
|
||||||
|
"nohash-hasher",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spacetimedb-sats"
|
||||||
|
version = "1.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df06586ffc862efd795425854cc2469c561aca5b95f5df2212aa29ef14a56f8a"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"arrayvec",
|
||||||
|
"bitflags 2.11.0",
|
||||||
|
"bytemuck",
|
||||||
|
"bytes",
|
||||||
|
"chrono",
|
||||||
|
"decorum",
|
||||||
|
"derive_more 0.99.20",
|
||||||
|
"enum-as-inner",
|
||||||
|
"ethnum",
|
||||||
|
"hex",
|
||||||
|
"itertools 0.12.1",
|
||||||
|
"rand 0.9.2",
|
||||||
|
"second-stack",
|
||||||
|
"sha3",
|
||||||
|
"smallvec",
|
||||||
|
"spacetimedb-bindings-macro",
|
||||||
|
"spacetimedb-primitives",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.9.8"
|
version = "0.9.8"
|
||||||
@@ -7996,7 +8284,7 @@ dependencies = [
|
|||||||
"gdkwayland-sys",
|
"gdkwayland-sys",
|
||||||
"gdkx11-sys",
|
"gdkx11-sys",
|
||||||
"gtk",
|
"gtk",
|
||||||
"jni",
|
"jni 0.21.1",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"ndk",
|
"ndk",
|
||||||
@@ -9223,12 +9511,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webbrowser"
|
name = "webbrowser"
|
||||||
version = "1.1.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f00bb839c1cf1e3036066614cbdcd035ecf215206691ea646aa3c60a24f68f2"
|
checksum = "fe985f41e291eecef5e5c0770a18d28390addb03331c043964d9e916453d6f16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core-foundation 0.10.1",
|
"core-foundation 0.10.1",
|
||||||
"jni",
|
"jni 0.22.3",
|
||||||
"log",
|
"log",
|
||||||
"ndk-context",
|
"ndk-context",
|
||||||
"objc2",
|
"objc2",
|
||||||
@@ -10050,7 +10338,7 @@ dependencies = [
|
|||||||
"html5ever",
|
"html5ever",
|
||||||
"http 1.4.0",
|
"http 1.4.0",
|
||||||
"javascriptcore-rs",
|
"javascriptcore-rs",
|
||||||
"jni",
|
"jni 0.21.1",
|
||||||
"kuchikiki",
|
"kuchikiki",
|
||||||
"libc",
|
"libc",
|
||||||
"ndk",
|
"ndk",
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ members = [
|
|||||||
"packages/marts",
|
"packages/marts",
|
||||||
"packages/mize",
|
"packages/mize",
|
||||||
"packages/ppc",
|
"packages/ppc",
|
||||||
|
"packages/spacetime-module-ppc",
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|||||||
@@ -3,6 +3,5 @@
|
|||||||
"./packages/ppc/platform/obsidian",
|
"./packages/ppc/platform/obsidian",
|
||||||
"./packages/marts",
|
"./packages/marts",
|
||||||
"./packages/mize"
|
"./packages/mize"
|
||||||
],
|
]
|
||||||
"imports": {}
|
|
||||||
}
|
}
|
||||||
|
|||||||
11
deno.lock
generated
11
deno.lock
generated
@@ -8,11 +8,12 @@
|
|||||||
"jsr:@std/path@^1.1.1": "1.1.4",
|
"jsr:@std/path@^1.1.1": "1.1.4",
|
||||||
"npm:@flowershow/remark-wiki-link@^3.4.0": "3.4.0",
|
"npm:@flowershow/remark-wiki-link@^3.4.0": "3.4.0",
|
||||||
"npm:builtin-modules@5": "5.0.0",
|
"npm:builtin-modules@5": "5.0.0",
|
||||||
"npm:esbuild@*": "0.25.12",
|
"npm:esbuild@*": "0.27.3",
|
||||||
"npm:esbuild@~0.25.5": "0.25.12",
|
"npm:esbuild@~0.25.5": "0.25.12",
|
||||||
"npm:esbuild@~0.27.3": "0.27.3",
|
"npm:esbuild@~0.27.3": "0.27.3",
|
||||||
"npm:mdast@3": "3.0.0",
|
"npm:mdast@3": "3.0.0",
|
||||||
"npm:obsidian@^1.12.2": "1.12.2_@codemirror+state@6.5.0_@codemirror+view@6.38.6",
|
"npm:obsidian@^1.12.2": "1.12.3_@codemirror+state@6.5.0_@codemirror+view@6.38.6",
|
||||||
|
"npm:obsidian@^1.12.3": "1.12.3_@codemirror+state@6.5.0_@codemirror+view@6.38.6",
|
||||||
"npm:remark-frontmatter@5": "5.0.0",
|
"npm:remark-frontmatter@5": "5.0.0",
|
||||||
"npm:remark-gfm@^4.0.1": "4.0.1",
|
"npm:remark-gfm@^4.0.1": "4.0.1",
|
||||||
"npm:remark-parse@11": "11.0.0",
|
"npm:remark-parse@11": "11.0.0",
|
||||||
@@ -876,8 +877,8 @@
|
|||||||
"ms@2.1.3": {
|
"ms@2.1.3": {
|
||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||||
},
|
},
|
||||||
"obsidian@1.12.2_@codemirror+state@6.5.0_@codemirror+view@6.38.6": {
|
"obsidian@1.12.3_@codemirror+state@6.5.0_@codemirror+view@6.38.6": {
|
||||||
"integrity": "sha512-DGAzpt6vo+sMDET/o8Zj26Bj2hbHrFsNUU8TtnzCyerO/OHksMFQnU9QEnPHVsOMstt/WnHXfC56j2r1syObWg==",
|
"integrity": "sha512-HxWqe763dOqzXjnNiHmAJTRERN8KILBSqxDSEqbeSr7W8R8Jxezzbca+nz1LiiqXnMpM8lV2jzAezw3CZ4xNUw==",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"@codemirror/state",
|
"@codemirror/state",
|
||||||
"@codemirror/view",
|
"@codemirror/view",
|
||||||
@@ -1001,7 +1002,7 @@
|
|||||||
"npm:builtin-modules@5",
|
"npm:builtin-modules@5",
|
||||||
"npm:esbuild@~0.27.3",
|
"npm:esbuild@~0.27.3",
|
||||||
"npm:mdast@3",
|
"npm:mdast@3",
|
||||||
"npm:obsidian@^1.12.2",
|
"npm:obsidian@^1.12.3",
|
||||||
"npm:remark-frontmatter@5",
|
"npm:remark-frontmatter@5",
|
||||||
"npm:remark-gfm@^4.0.1",
|
"npm:remark-gfm@^4.0.1",
|
||||||
"npm:remark-parse@11",
|
"npm:remark-parse@11",
|
||||||
|
|||||||
0
packages/mize/flake.lock → flake.lock
generated
0
packages/mize/flake.lock → flake.lock
generated
@@ -212,7 +212,86 @@ in {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
default = (mizeLib.buildMizeForSystem system).modules.mize.devShell;
|
#default = (mizeLib.buildMizeForSystem system).modules.mize.devShell;
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
|
||||||
|
MIZE_BUILD_CONFIG = let
|
||||||
|
settingsFormat = pkgs.formats.toml { };
|
||||||
|
in settingsFormat.generate "mize-build-config.toml" {
|
||||||
|
config = {
|
||||||
|
namespace = "mize.buildtime.ns";
|
||||||
|
module_url = "c2vi.dev";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
shellHook = ''
|
||||||
|
mize_project_root=$(${pkgs.lib.getExe pkgs.git} rev-parse --show-toplevel)
|
||||||
|
export MIZE_CONFIG_FILES=$mize_project_root/mize_config.toml
|
||||||
|
'';
|
||||||
|
#_shell_type = "rust";
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.wasm-pack
|
||||||
|
pkgs.dioxus-cli
|
||||||
|
pkgs.spacetimedb
|
||||||
|
pkgs.deno
|
||||||
|
pkgs.pkg-config
|
||||||
|
pkgs.gobject-introspection
|
||||||
|
pkgs.gobject-introspection.dev
|
||||||
|
|
||||||
|
# thanks to: https://github.com/NixOS/nixpkgs/pull/496279/changes
|
||||||
|
(pkgs.buildWasmBindgenCli rec {
|
||||||
|
src = pkgs.fetchCrate {
|
||||||
|
pname = "wasm-bindgen-cli";
|
||||||
|
version = "0.2.114";
|
||||||
|
hash = "sha256-xrCym+rFY6EUQFWyWl6OPA+LtftpUAE5pIaElAIVqW0=";
|
||||||
|
};
|
||||||
|
|
||||||
|
cargoDeps = pkgs.rustPlatform.fetchCargoVendor {
|
||||||
|
inherit src;
|
||||||
|
inherit (src) pname version;
|
||||||
|
hash = "sha256-Z8+dUXPQq7S+Q7DWNr2Y9d8GMuEdSnq00quUR0wDNPM=";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
(fenix.packages.${system}.combine [
|
||||||
|
fenix.packages.${system}.latest.toolchain
|
||||||
|
fenix.packages.${system}.targets.wasm32-unknown-unknown.latest.toolchain
|
||||||
|
])
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
at-spi2-atk
|
||||||
|
atkmm
|
||||||
|
cairo
|
||||||
|
gdk-pixbuf
|
||||||
|
glib
|
||||||
|
gtk3
|
||||||
|
harfbuzz
|
||||||
|
librsvg
|
||||||
|
libsoup_3
|
||||||
|
pango
|
||||||
|
webkitgtk_4_1
|
||||||
|
openssl
|
||||||
|
wasm-bindgen-cli
|
||||||
|
lld_20
|
||||||
|
xdotool
|
||||||
|
];
|
||||||
|
|
||||||
|
LD_LIBRARY_PATH = with pkgs; pkgs.lib.makeLibraryPath [
|
||||||
|
xdotool
|
||||||
|
webkitgtk_4_1
|
||||||
|
pango
|
||||||
|
openssl
|
||||||
|
at-spi2-atk
|
||||||
|
atkmm
|
||||||
|
cairo
|
||||||
|
gdk-pixbuf
|
||||||
|
glib
|
||||||
|
gtk3
|
||||||
|
harfbuzz
|
||||||
|
librsvg
|
||||||
|
libsoup_3
|
||||||
|
];
|
||||||
|
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}) // {
|
}) // {
|
||||||
55
md
55
md
@@ -1,5 +1,56 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
if [[ "$1" == "dob" ]]; then
|
MIZE_SRC="/home/me/work/mize" # hardcoded for now
|
||||||
|
RSYNC_EXCLUDES="--exclude=.git --exclude=node_modules --exclude=target --exclude=mize_config.toml --exclude=rust_dist --exclude=deno_dist --exclude=dist --exclude=result --exclude=pkg"
|
||||||
|
|
||||||
|
function main {
|
||||||
|
if [[ "$1" == "dlu" ]]; then
|
||||||
|
deploy_lush
|
||||||
|
fi
|
||||||
|
|
||||||
fi
|
if [[ "$1" == "dma" ]]; then
|
||||||
|
deploy_lush
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$1" == "dmo" ]]; then
|
||||||
|
deploy_main_obsidian
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function deploy_lush {
|
||||||
|
echo "c2vi: Deploying to lush..."
|
||||||
|
|
||||||
|
# Copy files to lush
|
||||||
|
rsync -r -u -v --delete --mkpath $RSYNC_EXCLUDES $MIZE_SRC/* lush:here/mize
|
||||||
|
|
||||||
|
# compile
|
||||||
|
ssh lush nix develop /home/me/here/mize --impure -v -L -c sh -c "cargo build --release --manifest-path /home/me/here/mize/packages/ppc/Cargo.toml"
|
||||||
|
|
||||||
|
# restart service
|
||||||
|
ssh lush "sudo systemctl restart ppc"
|
||||||
|
}
|
||||||
|
|
||||||
|
function deploy_main_website {
|
||||||
|
echo "c2vi: Deploying website to ppc-hosting..."
|
||||||
|
|
||||||
|
# Copy files to lush
|
||||||
|
rsync -r -u -v --delete --mkpath $RSYNC_EXCLUDES $MIZE_SRC/* ppc-hosting:ppc-src
|
||||||
|
|
||||||
|
# compile
|
||||||
|
ssh ppc-hosting nix develop /root/host/ppc-src --impure -v -L -c sh -c "cargo build --release --manifest-path /root/host/ppc-src/packages/ppc/Cargo.toml"
|
||||||
|
|
||||||
|
# restart service
|
||||||
|
ssh ppc-hosting "sudo systemctl restart ppc"
|
||||||
|
}
|
||||||
|
|
||||||
|
function deploy_main_obsidian {
|
||||||
|
echo "c2vi: Deploying to local main obsidian vault..."
|
||||||
|
|
||||||
|
deno run --config $MIZE_SRC/packages/ppc/platform/obsidian/deno.json build
|
||||||
|
|
||||||
|
cp -r $MIZE_SRC/packages/ppc/platform/obsidian/dist/* ~/work/things/.obsidian/plugins/ppc/
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|||||||
@@ -18,10 +18,11 @@ reqwest = { version = "0.13.2", features = ["blocking", "json"] }
|
|||||||
serde = "1.0.228"
|
serde = "1.0.228"
|
||||||
serde_json = "1.0.149"
|
serde_json = "1.0.149"
|
||||||
rusqlite = { version = "0.31", features = ["bundled"], optional = true }
|
rusqlite = { version = "0.31", features = ["bundled"], optional = true }
|
||||||
|
dioxus = { version = "0.7.1", features = ["router", "fullstack", "web", "desktop", "mobile", "server", "ssr"], optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["target-os"]
|
default = ["target-os"]
|
||||||
target-os = [ "clap", "mize/target-os", "rustyscript", "rusqlite" ]
|
target-os = [ "clap", "mize/target-os", "rustyscript", "rusqlite", "dioxus" ]
|
||||||
target-wasm = [ "mize/target-wasm" ]
|
target-wasm = [ "mize/target-wasm" ]
|
||||||
clap = ["dep:clap"]
|
clap = ["dep:clap"]
|
||||||
|
|
||||||
|
|||||||
9
packages/marts/c2vi/dashboard.rs
Normal file
9
packages/marts/c2vi/dashboard.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
pub fn main() -> Element {
|
||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
h1 { "my dashbaord" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,8 @@ use mize::{mize_err, mize_part, Mize, MizeError, MizePart, MizeResult};
|
|||||||
use crate::cli::CliPart;
|
use crate::cli::CliPart;
|
||||||
use crate::habitica::Habitica;
|
use crate::habitica::Habitica;
|
||||||
|
|
||||||
|
mod dashboard;
|
||||||
|
|
||||||
#[mize_part]
|
#[mize_part]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct C2vi {
|
pub struct C2vi {
|
||||||
@@ -40,7 +42,9 @@ impl C2vi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn c2vi(mize: &mut Mize) -> MizeResult<()> {
|
pub fn c2vi(mize: &mut Mize) -> MizeResult<()> {
|
||||||
let storage_path = mize.get_config("c2vi.local_storage_path")?.to_string();
|
//let storage_path = mize.get_config("c2vi.local_storage_path")?.as_
|
||||||
|
let storage_path = "/home/me/work/app-data/ppc";
|
||||||
|
println!("storage_path: {}", storage_path);
|
||||||
let db_path = std::path::PathBuf::from(&storage_path).join("data.db");
|
let db_path = std::path::PathBuf::from(&storage_path).join("data.db");
|
||||||
let conn = Connection::open(&db_path)
|
let conn = Connection::open(&db_path)
|
||||||
.map_err(|e| mize_err!("Failed to open C2vi database at {:?}: {}", db_path, e))?;
|
.map_err(|e| mize_err!("Failed to open C2vi database at {:?}: {}", db_path, e))?;
|
||||||
@@ -84,6 +88,10 @@ fn setup_tables(conn: &Connection) -> MizeResult<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn register_subcommands(cli: &mut CliPart) {
|
fn register_subcommands(cli: &mut CliPart) {
|
||||||
|
cli.subcommand(
|
||||||
|
Command::new("c2vi-dash").about("Run the c2vi dashboard gui"),
|
||||||
|
|_matches, mut mize| Ok(dioxus::launch(dashboard::main)),
|
||||||
|
);
|
||||||
cli.subcommand(
|
cli.subcommand(
|
||||||
Command::new("bed").about("Command to run when c2vi goes to bed"),
|
Command::new("bed").about("Command to run when c2vi goes to bed"),
|
||||||
|_matches, mut mize| {
|
|_matches, mut mize| {
|
||||||
@@ -184,10 +192,7 @@ fn register_subcommands(cli: &mut CliPart) {
|
|||||||
.map_err(|e| mize_err!("DB error: {}", e))?;
|
.map_err(|e| mize_err!("DB error: {}", e))?;
|
||||||
let rows = stmt
|
let rows = stmt
|
||||||
.query_map([], |row| {
|
.query_map([], |row| {
|
||||||
Ok((
|
Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?))
|
||||||
row.get::<_, String>(0)?,
|
|
||||||
row.get::<_, String>(1)?,
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
.map_err(|e| mize_err!("DB error: {}", e))?;
|
.map_err(|e| mize_err!("DB error: {}", e))?;
|
||||||
for row in rows {
|
for row in rows {
|
||||||
@@ -206,15 +211,17 @@ fn register_subcommands(cli: &mut CliPart) {
|
|||||||
|matches, mut mize| {
|
|matches, mut mize| {
|
||||||
let id = matches.get_one::<String>("id").unwrap();
|
let id = matches.get_one::<String>("id").unwrap();
|
||||||
let mut hab = mize.get_part_native::<Habitica>("habitica")?;
|
let mut hab = mize.get_part_native::<Habitica>("habitica")?;
|
||||||
let data = hab.api_request(
|
let data = hab.api_request(reqwest::Method::GET, format!("tasks/{}", id), json!({}))?;
|
||||||
reqwest::Method::GET,
|
|
||||||
format!("tasks/{}", id),
|
|
||||||
json!({}),
|
|
||||||
)?;
|
|
||||||
if let Some(history) = data.get("history") {
|
if let Some(history) = data.get("history") {
|
||||||
println!("{}", serde_json::to_string_pretty(history).unwrap_or_default());
|
println!(
|
||||||
|
"{}",
|
||||||
|
serde_json::to_string_pretty(history).unwrap_or_default()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("{}", serde_json::to_string_pretty(&data).unwrap_or_default());
|
println!(
|
||||||
|
"{}",
|
||||||
|
serde_json::to_string_pretty(&data).unwrap_or_default()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
@@ -250,9 +257,7 @@ fn get_or_create_log(conn: &Connection, date: &str) -> MizeResult<Value> {
|
|||||||
let mut stmt = conn
|
let mut stmt = conn
|
||||||
.prepare("SELECT data FROM habitica_log WHERE date = ?1")
|
.prepare("SELECT data FROM habitica_log WHERE date = ?1")
|
||||||
.map_err(|e| mize_err!("DB error: {}", e))?;
|
.map_err(|e| mize_err!("DB error: {}", e))?;
|
||||||
let result: Option<String> = stmt
|
let result: Option<String> = stmt.query_row(params![date], |row| row.get(0)).ok();
|
||||||
.query_row(params![date], |row| row.get(0))
|
|
||||||
.ok();
|
|
||||||
match result {
|
match result {
|
||||||
Some(data_str) => {
|
Some(data_str) => {
|
||||||
serde_json::from_str(&data_str).map_err(|e| mize_err!("JSON parse error: {}", e))
|
serde_json::from_str(&data_str).map_err(|e| mize_err!("JSON parse error: {}", e))
|
||||||
@@ -394,7 +399,10 @@ fn save_habitica_logs(mize: &mut Mize) -> MizeResult<()> {
|
|||||||
if save_for_yesterday {
|
if save_for_yesterday {
|
||||||
let existing_todos = data["todos_done"].as_array().unwrap();
|
let existing_todos = data["todos_done"].as_array().unwrap();
|
||||||
let todo_id = todo["id"].as_str().unwrap_or("");
|
let todo_id = todo["id"].as_str().unwrap_or("");
|
||||||
if existing_todos.iter().any(|t| t["id"].as_str() == Some(todo_id)) {
|
if existing_todos
|
||||||
|
.iter()
|
||||||
|
.any(|t| t["id"].as_str() == Some(todo_id))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -419,10 +427,7 @@ fn save_habitica_logs(mize: &mut Mize) -> MizeResult<()> {
|
|||||||
// If saving for yesterday but todo was completed today, also record it
|
// If saving for yesterday but todo was completed today, also record it
|
||||||
if save_for_yesterday && date_completed == today_str {
|
if save_for_yesterday && date_completed == today_str {
|
||||||
println!("todo-done: {}", todo["text"].as_str().unwrap_or(""));
|
println!("todo-done: {}", todo["text"].as_str().unwrap_or(""));
|
||||||
data["todos_done"]
|
data["todos_done"].as_array_mut().unwrap().push(todo_entry);
|
||||||
.as_array_mut()
|
|
||||||
.unwrap()
|
|
||||||
.push(todo_entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -441,7 +446,9 @@ fn skip_habitica_todo(mize: &mut Mize, num: usize) -> MizeResult<()> {
|
|||||||
hab.get_tasks("todos")?
|
hab.get_tasks("todos")?
|
||||||
};
|
};
|
||||||
|
|
||||||
let arr = todos.as_array().ok_or_else(|| mize_err!("Expected array of todos"))?;
|
let arr = todos
|
||||||
|
.as_array()
|
||||||
|
.ok_or_else(|| mize_err!("Expected array of todos"))?;
|
||||||
|
|
||||||
// Delete and log each skipped todo
|
// Delete and log each skipped todo
|
||||||
for i in 0..num {
|
for i in 0..num {
|
||||||
@@ -517,10 +524,8 @@ se 21:40
|
|||||||
read
|
read
|
||||||
bed 22:10";
|
bed 22:10";
|
||||||
|
|
||||||
let tmp_file = std::env::temp_dir().join(format!(
|
let tmp_file =
|
||||||
"habitica-tasks-{}.md",
|
std::env::temp_dir().join(format!("habitica-tasks-{}.md", Utc::now().timestamp()));
|
||||||
Utc::now().timestamp()
|
|
||||||
));
|
|
||||||
std::fs::write(&tmp_file, initial_content)
|
std::fs::write(&tmp_file, initial_content)
|
||||||
.map_err(|e| mize_err!("Failed to write temp file: {}", e))?;
|
.map_err(|e| mize_err!("Failed to write temp file: {}", e))?;
|
||||||
|
|
||||||
@@ -531,8 +536,8 @@ bed 22:10";
|
|||||||
.map_err(|e| mize_err!("Failed to run nvim: {}", e))?;
|
.map_err(|e| mize_err!("Failed to run nvim: {}", e))?;
|
||||||
|
|
||||||
// Read back and parse
|
// Read back and parse
|
||||||
let list_str =
|
let list_str = std::fs::read_to_string(&tmp_file)
|
||||||
std::fs::read_to_string(&tmp_file).map_err(|e| mize_err!("Failed to read temp file: {}", e))?;
|
.map_err(|e| mize_err!("Failed to read temp file: {}", e))?;
|
||||||
let _ = std::fs::remove_file(&tmp_file);
|
let _ = std::fs::remove_file(&tmp_file);
|
||||||
|
|
||||||
let tasks: Vec<&str> = list_str
|
let tasks: Vec<&str> = list_str
|
||||||
@@ -577,17 +582,18 @@ fn dump_habitica_logs(mize: &mut Mize) -> MizeResult<()> {
|
|||||||
.map_err(|e| mize_err!("DB error: {}", e))?;
|
.map_err(|e| mize_err!("DB error: {}", e))?;
|
||||||
let rows = stmt
|
let rows = stmt
|
||||||
.query_map([], |row| {
|
.query_map([], |row| {
|
||||||
Ok((
|
Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?))
|
||||||
row.get::<_, String>(0)?,
|
|
||||||
row.get::<_, String>(1)?,
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
.map_err(|e| mize_err!("DB error: {}", e))?;
|
.map_err(|e| mize_err!("DB error: {}", e))?;
|
||||||
for row in rows {
|
for row in rows {
|
||||||
let (date, data_str) = row.map_err(|e| mize_err!("DB error: {}", e))?;
|
let (date, data_str) = row.map_err(|e| mize_err!("DB error: {}", e))?;
|
||||||
let data: Value =
|
let data: Value =
|
||||||
serde_json::from_str(&data_str).unwrap_or(json!({"parse_error": data_str}));
|
serde_json::from_str(&data_str).unwrap_or(json!({"parse_error": data_str}));
|
||||||
println!("{}: {}", date, serde_json::to_string_pretty(&data).unwrap_or_default());
|
println!(
|
||||||
|
"{}: {}",
|
||||||
|
date,
|
||||||
|
serde_json::to_string_pretty(&data).unwrap_or_default()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,10 +2,7 @@
|
|||||||
"name": "@ppc/marts",
|
"name": "@ppc/marts",
|
||||||
"imports": {},
|
"imports": {},
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./index.ts",
|
".": "./index.ts"
|
||||||
"stub_deno": "./js/stub_deno.ts"
|
|
||||||
},
|
},
|
||||||
"tasks": {
|
"tasks": {}
|
||||||
"build": "deno bundle -o ./deno_dist/habitica.js ./habitica.ts && deno -A ./esbuild.config.mjs"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
export { task_obsidian_otask_parse } from "./task/obsidian-otask-parse";
|
export * from "./task/obsidian-otask-parse";
|
||||||
export { c2vi_obsidian_canvas_patch } from "./c2vi/obsidian-canvas-patch";
|
export * from "./c2vi/obsidian-canvas-patch";
|
||||||
|
|
||||||
|
export * from "./js/stub_deno";
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub mod c2vi;
|
|||||||
#[cfg(feature = "target-os")]
|
#[cfg(feature = "target-os")]
|
||||||
pub use c2vi::*;
|
pub use c2vi::*;
|
||||||
|
|
||||||
#[cfg(feature = "target-os")]
|
//#[cfg(feature = "target-os")]
|
||||||
pub mod js;
|
//pub mod js;
|
||||||
#[cfg(feature = "target-os")]
|
//#[cfg(feature = "target-os")]
|
||||||
pub use js::*;
|
//pub use js::*;
|
||||||
|
|||||||
@@ -1,21 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "marts",
|
"name": "@ppc/marts",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"packageManager": "pnpm@10.15.1",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@flowershow/remark-wiki-link": "^3.4.0",
|
"@flowershow/remark-wiki-link": "^3.4.0",
|
||||||
"builtin-modules": "^5.0.0",
|
"builtin-modules": "^5.0.0",
|
||||||
"esbuild": "^0.27.3",
|
"esbuild": "^0.27.3",
|
||||||
"mdast": "^3.0.0",
|
"mdast": "^3.0.0",
|
||||||
"obsidian": "^1.12.2",
|
"obsidian": "^1.12.3",
|
||||||
"remark-frontmatter": "^5.0.0",
|
"remark-frontmatter": "^5.0.0",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"remark-parse": "^11.0.0",
|
"remark-parse": "^11.0.0",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { id, i, init, InstaQLEntity } from "@instantdb/react";
|
|
||||||
import remarkParse from "remark-parse";
|
import remarkParse from "remark-parse";
|
||||||
import remarkStringify from "remark-stringify";
|
import remarkStringify from "remark-stringify";
|
||||||
import { unified } from "unified";
|
import { unified } from "unified";
|
||||||
@@ -7,6 +6,7 @@ import { Root, Content, Heading, List, ListItem, Text } from "mdast";
|
|||||||
import remarkFrontmatter from "remark-frontmatter";
|
import remarkFrontmatter from "remark-frontmatter";
|
||||||
import remarkGfm from "remark-gfm";
|
import remarkGfm from "remark-gfm";
|
||||||
import wikiLinkPlugin from "@flowershow/remark-wiki-link";
|
import wikiLinkPlugin from "@flowershow/remark-wiki-link";
|
||||||
|
import { TFile } from "obsidian";
|
||||||
|
|
||||||
const OTASK_PROP_NAMES = ["short", "outcome", "priority"];
|
const OTASK_PROP_NAMES = ["short", "outcome", "priority"];
|
||||||
const ACTION_PROP_NAMES = [];
|
const ACTION_PROP_NAMES = [];
|
||||||
@@ -77,7 +77,7 @@ async function full_parse() {
|
|||||||
render_sub0_file(OTASK_LIST);
|
render_sub0_file(OTASK_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
let OTASK_PARSE_QUEUE = [];
|
let OTASK_PARSE_QUEUE: any = [];
|
||||||
let OTASK_LIST = [];
|
let OTASK_LIST = [];
|
||||||
let DBG = false;
|
let DBG = false;
|
||||||
|
|
||||||
@@ -201,130 +201,37 @@ async function replaceHeading(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function otasks_from_list_item(listItem, otask_path, priority = 0) {
|
async function otasks_from_list_item(listItem, otask_path, priority = 0) {
|
||||||
// the main otask this listItem is about
|
try {
|
||||||
let otask = {
|
// the main otask this listItem is about
|
||||||
description: [],
|
let otask = {
|
||||||
actions: [],
|
description: [],
|
||||||
path: [],
|
actions: [],
|
||||||
priority,
|
path: [],
|
||||||
};
|
priority,
|
||||||
dbg("SystemC2: otasks_from_list_item", listItem, otask_path);
|
};
|
||||||
|
dbg("SystemC2: otasks_from_list_item", listItem, otask_path);
|
||||||
|
|
||||||
if (!listItem.children[0].type === "paragraph") {
|
if (!listItem.children[0].type === "paragraph") {
|
||||||
dbg(
|
dbg(
|
||||||
"listItem[0] of a otask item is not a paragraph... the otask:",
|
"listItem[0] of a otask item is not a paragraph... the otask:",
|
||||||
listItem,
|
listItem,
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
let longName = nodeToString(listItem.children[0]);
|
|
||||||
|
|
||||||
dbg("longName:", longName);
|
|
||||||
|
|
||||||
// check for [[anotherotask]], call otasks_from_file, return those
|
|
||||||
const match = longName.match(/\[\[([^\]]+)\]\]/);
|
|
||||||
if (match) {
|
|
||||||
const file = app.metadataCache.getFirstLinkpathDest(match[1], "");
|
|
||||||
if (file) {
|
|
||||||
const metadata = app.metadataCache.getFileCache(file);
|
|
||||||
|
|
||||||
if (metadata?.frontmatter?.tags?.includes("t/otask")) {
|
|
||||||
queue_otasks_from_file(file, otask_path);
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
dbg(
|
|
||||||
"SystemC2: listItem with Link to '",
|
|
||||||
match[1],
|
|
||||||
"', which is not an otask",
|
|
||||||
longName,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
let longName = nodeToString(listItem.children[0]);
|
||||||
|
|
||||||
//check for [x] and remove from name
|
dbg("longName:", longName);
|
||||||
if (longName.startsWith("[ ") || longName.startsWith("[x")) {
|
|
||||||
longName = longName.slice(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
//check for "ot:" and remove from name
|
// check for [[anotherotask]], call otasks_from_file, return those
|
||||||
if (longName.startsWith("ot:")) {
|
const match = longName.match(/\[\[([^\]]+)\]\]/);
|
||||||
longName = longName.slice(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
otask.longName = longName;
|
|
||||||
otask.short = longName;
|
|
||||||
otask.path = otask_path;
|
|
||||||
let new_otask_path = [...otask_path, otask.short];
|
|
||||||
|
|
||||||
// go through sub list items
|
|
||||||
// - if it's a prop for the otask... handle that
|
|
||||||
// - if it's an "ac:" handle that
|
|
||||||
// - if it's "ot: " handle as another otask -> recursive call
|
|
||||||
// - if it's "[ ]" handle as another otask -> recursive call
|
|
||||||
// - if it's a link to a otask file... handle as another otask -> call otasks_from_file()
|
|
||||||
// - else add it as description item list to otask
|
|
||||||
if (!listItem.children || listItem.children.length < 2) {
|
|
||||||
return otask;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add content as text to otask
|
|
||||||
if (otask.longName == "hosting updates") {
|
|
||||||
console.log("listItem... ", listItem.children[1]);
|
|
||||||
let hii = REMARK.stringify(listItem.children[1]);
|
|
||||||
console.log("text...", hii);
|
|
||||||
}
|
|
||||||
let content_text = REMARK.stringify(listItem.children[1]);
|
|
||||||
otask.content = content_text;
|
|
||||||
|
|
||||||
for (const subListItem of listItem.children[1].children) {
|
|
||||||
let text = nodeToString(subListItem.children[0]);
|
|
||||||
|
|
||||||
// check prop
|
|
||||||
if (check_otask_prop_from_list_item(subListItem, otask)) {
|
|
||||||
new_otask_path = [...otask_path, otask.short]; // have to redo it here, in case short changed from aprop
|
|
||||||
continue; // don't do any other processing on this sub-listItem
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove "[ ]"
|
|
||||||
if (text.startsWith("[ ") || text.startsWith("[x")) {
|
|
||||||
text = text.slice(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check ac
|
|
||||||
if (text.startsWith("ac:")) {
|
|
||||||
otask.actions = [
|
|
||||||
...otask.actions,
|
|
||||||
action_from_list_item(subListItem, new_otask_path, otask.priority),
|
|
||||||
];
|
|
||||||
|
|
||||||
continue; // don't do any other processing on this sub-listItem
|
|
||||||
}
|
|
||||||
|
|
||||||
// check ot
|
|
||||||
if (text.startsWith("ot:")) {
|
|
||||||
queue_otasks_from_list_item(subListItem, new_otask_path, otask.priority);
|
|
||||||
|
|
||||||
continue; // don't do any other processing on this sub-listItem
|
|
||||||
}
|
|
||||||
|
|
||||||
// check [ ]
|
|
||||||
if (text.startsWith("[ ] ") || text.startsWith("[x] ")) {
|
|
||||||
queue_otasks_from_list_item(subListItem, new_otask_path, otask.priority);
|
|
||||||
|
|
||||||
continue; // don't do any other processing on this sub-listItem
|
|
||||||
}
|
|
||||||
|
|
||||||
// check link to otask file
|
|
||||||
const match = text.match(/\[\[([^\]]+)\]\]/);
|
|
||||||
if (match) {
|
if (match) {
|
||||||
const file = app.metadataCache.getFirstLinkpathDest(match[1], "");
|
const file = app.metadataCache.getFirstLinkpathDest(match[1], "");
|
||||||
if (file) {
|
if (file) {
|
||||||
const metadata = app.metadataCache.getFileCache(file);
|
const metadata = app.metadataCache.getFileCache(file);
|
||||||
|
|
||||||
if (metadata?.frontmatter?.tags?.includes("t/otask")) {
|
if (metadata?.frontmatter?.tags?.includes("t/otask")) {
|
||||||
queue_otasks_from_file(file, new_otask_path, otask.priority);
|
queue_otasks_from_file(file, otask_path);
|
||||||
continue;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
dbg(
|
dbg(
|
||||||
"SystemC2: listItem with Link to '",
|
"SystemC2: listItem with Link to '",
|
||||||
@@ -333,83 +240,192 @@ async function otasks_from_list_item(listItem, otask_path, priority = 0) {
|
|||||||
longName,
|
longName,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//check for [x] and remove from name
|
||||||
|
if (longName.startsWith("[ ") || longName.startsWith("[x")) {
|
||||||
|
longName = longName.slice(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check for "ot:" and remove from name
|
||||||
|
if (longName.startsWith("ot:")) {
|
||||||
|
longName = longName.slice(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
otask.longName = longName;
|
||||||
|
otask.short = longName;
|
||||||
|
otask.path = otask_path;
|
||||||
|
let new_otask_path = [...otask_path, otask.short];
|
||||||
|
|
||||||
|
// go through sub list items
|
||||||
|
// - if it's a prop for the otask... handle that
|
||||||
|
// - if it's an "ac:" handle that
|
||||||
|
// - if it's "ot: " handle as another otask -> recursive call
|
||||||
|
// - if it's "[ ]" handle as another otask -> recursive call
|
||||||
|
// - if it's a link to a otask file... handle as another otask -> call otasks_from_file()
|
||||||
|
// - else add it as description item list to otask
|
||||||
|
if (!listItem.children || listItem.children.length < 2) {
|
||||||
|
return otask;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add content as text to otask
|
||||||
|
if (otask.longName == "hosting updates") {
|
||||||
|
console.log("listItem... ", listItem.children[1]);
|
||||||
|
let hii = REMARK.stringify(listItem.children[1]);
|
||||||
|
console.log("text...", hii);
|
||||||
|
}
|
||||||
|
let content_text = REMARK.stringify(listItem.children[1]);
|
||||||
|
otask.content = content_text;
|
||||||
|
|
||||||
|
for (const subListItem of listItem.children[1].children) {
|
||||||
|
let text = nodeToString(subListItem.children[0]);
|
||||||
|
|
||||||
|
// check prop
|
||||||
|
if (check_otask_prop_from_list_item(subListItem, otask)) {
|
||||||
|
new_otask_path = [...otask_path, otask.short]; // have to redo it here, in case short changed from aprop
|
||||||
|
continue; // don't do any other processing on this sub-listItem
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove "[ ]"
|
||||||
|
if (text.startsWith("[ ") || text.startsWith("[x")) {
|
||||||
|
text = text.slice(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check ac
|
||||||
|
if (text.startsWith("ac:")) {
|
||||||
|
otask.actions = [
|
||||||
|
...otask.actions,
|
||||||
|
action_from_list_item(subListItem, new_otask_path, otask.priority),
|
||||||
|
];
|
||||||
|
|
||||||
|
continue; // don't do any other processing on this sub-listItem
|
||||||
|
}
|
||||||
|
|
||||||
|
// check ot
|
||||||
|
if (text.startsWith("ot:")) {
|
||||||
|
queue_otasks_from_list_item(
|
||||||
|
subListItem,
|
||||||
|
new_otask_path,
|
||||||
|
otask.priority,
|
||||||
|
);
|
||||||
|
|
||||||
|
continue; // don't do any other processing on this sub-listItem
|
||||||
|
}
|
||||||
|
|
||||||
|
// check [ ]
|
||||||
|
if (text.startsWith("[ ] ") || text.startsWith("[x] ")) {
|
||||||
|
queue_otasks_from_list_item(
|
||||||
|
subListItem,
|
||||||
|
new_otask_path,
|
||||||
|
otask.priority,
|
||||||
|
);
|
||||||
|
|
||||||
|
continue; // don't do any other processing on this sub-listItem
|
||||||
|
}
|
||||||
|
|
||||||
|
// check link to otask file
|
||||||
|
const match = text.match(/\[\[([^\]]+)\]\]/);
|
||||||
|
if (match) {
|
||||||
|
const file = app.metadataCache.getFirstLinkpathDest(match[1], "");
|
||||||
|
if (file) {
|
||||||
|
const metadata = app.metadataCache.getFileCache(file);
|
||||||
|
|
||||||
|
if (metadata?.frontmatter?.tags?.includes("t/otask")) {
|
||||||
|
queue_otasks_from_file(file, new_otask_path, otask.priority);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
dbg(
|
||||||
|
"SystemC2: listItem with Link to '",
|
||||||
|
match[1],
|
||||||
|
"', which is not an otask",
|
||||||
|
longName,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue; // don't do any other processing on this sub-listItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add as description
|
||||||
|
const desc = REMARK.stringify(subListItem);
|
||||||
|
otask.description.push(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return otask;
|
||||||
|
} catch (error) {
|
||||||
|
console.log("failed to parse list item:", listItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function otasks_from_file(file: TFile, otask_path, priority = 0) {
|
||||||
|
try {
|
||||||
|
dbg("SystemC2: otasks_from_file", file, otask_path);
|
||||||
|
|
||||||
|
// the main otask this file is about
|
||||||
|
let otask = {
|
||||||
|
description: [],
|
||||||
|
actions: [],
|
||||||
|
path: [],
|
||||||
|
priority,
|
||||||
|
is_file: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
otask.longName = file.basename;
|
||||||
|
otask.short = otask.longName;
|
||||||
|
otask.path = otask_path;
|
||||||
|
let new_otask_path = [...otask_path, otask.short];
|
||||||
|
|
||||||
|
const content = await app.vault.read(file);
|
||||||
|
|
||||||
|
// parse listItems at the top... for props
|
||||||
|
const topListItems = getListItemsBeforeFirstHeading(content);
|
||||||
|
for (const topListItem of topListItems) {
|
||||||
|
const text = nodeToString(topListItem);
|
||||||
|
|
||||||
|
// check for prop
|
||||||
|
if (check_otask_prop_from_list_item(topListItem, otask)) {
|
||||||
|
new_otask_path = [...otask_path, otask.short];
|
||||||
continue; // don't do any other processing on this sub-listItem
|
continue; // don't do any other processing on this sub-listItem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add as description
|
// parse all the sub sections
|
||||||
const desc = REMARK.stringify(subListItem);
|
const SUB_COUNT = 10;
|
||||||
otask.description.push(desc);
|
for (let sub_number = 0; sub_number < SUB_COUNT; sub_number++) {
|
||||||
}
|
let listItems = await getListUnderHeading(content, "sub" + sub_number);
|
||||||
|
|
||||||
return otask;
|
// "sub" without a number should have priority 5
|
||||||
}
|
if (sub_number == 5) {
|
||||||
|
listItems = listItems.concat(await getListUnderHeading(content, "sub"));
|
||||||
async function otasks_from_file(file: TFile, otask_path, priority = 0) {
|
|
||||||
dbg("SystemC2: otasks_from_file", file, otask_path);
|
|
||||||
|
|
||||||
// the main otask this file is about
|
|
||||||
let otask = {
|
|
||||||
description: [],
|
|
||||||
actions: [],
|
|
||||||
path: [],
|
|
||||||
priority,
|
|
||||||
is_file: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
otask.longName = file.basename;
|
|
||||||
otask.short = otask.longName;
|
|
||||||
otask.path = otask_path;
|
|
||||||
let new_otask_path = [...otask_path, otask.short];
|
|
||||||
|
|
||||||
const content = await app.vault.read(file);
|
|
||||||
|
|
||||||
// parse listItems at the top... for props
|
|
||||||
const topListItems = getListItemsBeforeFirstHeading(content);
|
|
||||||
for (const topListItem of topListItems) {
|
|
||||||
const text = nodeToString(topListItem);
|
|
||||||
|
|
||||||
// check for prop
|
|
||||||
if (check_otask_prop_from_list_item(topListItem, otask)) {
|
|
||||||
new_otask_path = [...otask_path, otask.short];
|
|
||||||
continue; // don't do any other processing on this sub-listItem
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse all the sub sections
|
|
||||||
const SUB_COUNT = 10;
|
|
||||||
for (let sub_number = 0; sub_number < SUB_COUNT; sub_number++) {
|
|
||||||
let listItems = await getListUnderHeading(content, "sub" + sub_number);
|
|
||||||
|
|
||||||
// "sub" without a number should have priority 5
|
|
||||||
if (sub_number == 5) {
|
|
||||||
listItems = listItems.concat(await getListUnderHeading(content, "sub"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//dbg(`sub section ${sub_number} has items:`, listItems)
|
|
||||||
|
|
||||||
for (const listItem of listItems) {
|
|
||||||
// check if listItem is an action...
|
|
||||||
let text = nodeToString(listItem.children[0]);
|
|
||||||
if (
|
|
||||||
text.startsWith("ac:") ||
|
|
||||||
text.startsWith("[ ] ac:") ||
|
|
||||||
text.startsWith("[x] ac:")
|
|
||||||
) {
|
|
||||||
const action = action_from_list_item(listItem, otask_path);
|
|
||||||
otask.actions.push(action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_otasks_from_list_item(
|
//dbg(`sub section ${sub_number} has items:`, listItems)
|
||||||
listItem,
|
|
||||||
new_otask_path,
|
|
||||||
otask.priority + sub_number,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return otask;
|
for (const listItem of listItems) {
|
||||||
|
// check if listItem is an action...
|
||||||
|
let text = nodeToString(listItem.children[0]);
|
||||||
|
if (
|
||||||
|
text.startsWith("ac:") ||
|
||||||
|
text.startsWith("[ ] ac:") ||
|
||||||
|
text.startsWith("[x] ac:")
|
||||||
|
) {
|
||||||
|
const action = action_from_list_item(listItem, otask_path);
|
||||||
|
otask.actions.push(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_otasks_from_list_item(
|
||||||
|
listItem,
|
||||||
|
new_otask_path,
|
||||||
|
otask.priority + sub_number,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return otask;
|
||||||
|
} catch (error) {
|
||||||
|
console.log("failed to parse file: ", file.path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function action_from_list_item(listItem, otask_path) {
|
function action_from_list_item(listItem, otask_path) {
|
||||||
|
|||||||
@@ -53,9 +53,13 @@ pub fn gather_config(mize: &mut Mize) -> MizeResult<()> {
|
|||||||
let mut data = ItemData::from_toml(content.as_str())?;
|
let mut data = ItemData::from_toml(content.as_str())?;
|
||||||
println!("config data: {data}");
|
println!("config data: {data}");
|
||||||
for path in data.get_paths_recursive()? {
|
for path in data.get_paths_recursive()? {
|
||||||
let conf_name = path.replace("/", ".");
|
let mut conf_name = path.replace("/", ".");
|
||||||
|
if conf_name.starts_with(".") {
|
||||||
|
conf_name.remove(0);
|
||||||
|
}
|
||||||
println!("adding config {conf_name} from config file {config_file_path}");
|
println!("adding config {conf_name} from config file {config_file_path}");
|
||||||
let val = data.get_path(path.split("/").collect::<Vec<&str>>())?;
|
println!("path: {:?}", path);
|
||||||
|
let val = data.get_path(path.split("/").filter(|s| s != &"").collect::<Vec<&str>>())?;
|
||||||
match config_opts.get_mut(&conf_name) {
|
match config_opts.get_mut(&conf_name) {
|
||||||
Some(opt) => {
|
Some(opt) => {
|
||||||
opt.val = Some(val);
|
opt.val = Some(val);
|
||||||
|
|||||||
@@ -707,6 +707,7 @@ impl Mize {
|
|||||||
#[cfg(feature = "target-os")]
|
#[cfg(feature = "target-os")]
|
||||||
let handle = thread::spawn(move || to_spawn());
|
let handle = thread::spawn(move || to_spawn());
|
||||||
|
|
||||||
|
#[cfg(feature = "target-os")]
|
||||||
threads_inner.push((*next_thread_id, name.to_owned(), Some(handle)));
|
threads_inner.push((*next_thread_id, name.to_owned(), Some(handle)));
|
||||||
|
|
||||||
#[cfg(feature = "target-wasm ")]
|
#[cfg(feature = "target-wasm ")]
|
||||||
@@ -905,9 +906,10 @@ impl Mize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) -> MizeResult<()> {
|
pub fn run(&mut self) -> MizeResult<()> {
|
||||||
let mut parts = self.parts.lock().unwrap();
|
let part_names = self.part_names();
|
||||||
for part in parts.values_mut() {
|
for part_name in part_names {
|
||||||
part.as_deref_mut().unwrap().run(&mut self.clone())?;
|
let mut part = self.get_part(part_name)?;
|
||||||
|
part.run(&mut self.clone())?;
|
||||||
}
|
}
|
||||||
let mut threads_inner = self.threads.lock().unwrap();
|
let mut threads_inner = self.threads.lock().unwrap();
|
||||||
for (id, name, handle) in threads_inner.drain(..) {
|
for (id, name, handle) in threads_inner.drain(..) {
|
||||||
@@ -922,8 +924,12 @@ impl Mize {
|
|||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> MizeResult<MizePartGuard<T>> {
|
) -> MizeResult<MizePartGuard<T>> {
|
||||||
|
println!("Getting part native hiiiiiii");
|
||||||
let mut dyn_guard = self.get_part(name)?;
|
let mut dyn_guard = self.get_part(name)?;
|
||||||
|
println!("Getting part native hiiiiiii two");
|
||||||
let part = dyn_guard.part.take().unwrap();
|
let part = dyn_guard.part.take().unwrap();
|
||||||
|
println!("Getting part native hiiiiiii three");
|
||||||
|
drop(dyn_guard);
|
||||||
let concrete_part = part.into_any().downcast::<T>().unwrap();
|
let concrete_part = part.into_any().downcast::<T>().unwrap();
|
||||||
Ok(MizePartGuard {
|
Ok(MizePartGuard {
|
||||||
mize: self.clone(),
|
mize: self.clone(),
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ tracing = { version = "0.1.44", optional = true }
|
|||||||
tower = { version = "0.5", optional = true }
|
tower = { version = "0.5", optional = true }
|
||||||
tower-sessions = { version = "0.14.0", optional = true }
|
tower-sessions = { version = "0.14.0", optional = true }
|
||||||
tower-http = { version = "0.6.8", features = ["trace"] }
|
tower-http = { version = "0.6.8", features = ["trace"] }
|
||||||
|
webbrowser = { version = "1.2.0", optional = true }
|
||||||
|
base64 = { version = "0.22.1", optional = true }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "ppc"
|
name = "ppc"
|
||||||
@@ -41,7 +43,7 @@ name = "ppc"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["target-os"]
|
default = ["target-os"]
|
||||||
target-os = [ "clap", "mize/target-os", "marts/target-os", "server", "tracing" ]
|
target-os = [ "clap", "mize/target-os", "marts/target-os", "server", "tracing", "webbrowser", "base64" ]
|
||||||
target-obsidian = [ "js-sys", "wasm-bindgen", "mize/target-wasm", "marts/target-wasm" ]
|
target-obsidian = [ "js-sys", "wasm-bindgen", "mize/target-wasm", "marts/target-wasm" ]
|
||||||
server = [ "axum", "axum-extra", "openidconnect", "serde", "serde_json", "reqwest", "rand", "url", "time", "tokio", "dioxus", "dioxus-ssr", "html-escape", "axum-oidc", "tower", "tower-sessions" ]
|
server = [ "axum", "axum-extra", "openidconnect", "serde", "serde_json", "reqwest", "rand", "url", "time", "tokio", "dioxus", "dioxus-ssr", "html-escape", "axum-oidc", "tower", "tower-sessions" ]
|
||||||
|
|
||||||
|
|||||||
221
packages/ppc/auth/client.rs
Normal file
221
packages/ppc/auth/client.rs
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
use base64::{
|
||||||
|
Engine,
|
||||||
|
alphabet::STANDARD,
|
||||||
|
engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig},
|
||||||
|
};
|
||||||
|
use clap::Command;
|
||||||
|
use mize::{Mize, MizeError, MizePart, MizeResult, mize_err, mize_part};
|
||||||
|
use openidconnect::{
|
||||||
|
AuthorizationCode, ClientId, CsrfToken, IssuerUrl, Nonce, OAuth2TokenResponse,
|
||||||
|
PkceCodeChallenge, PkceCodeVerifier, RedirectUrl, RefreshToken, Scope,
|
||||||
|
core::{CoreAuthenticationFlow, CoreClient, CoreProviderMetadata},
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{
|
||||||
|
io::{self, Write},
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
#[mize_part]
|
||||||
|
pub struct ClientAuth {
|
||||||
|
mize: Mize,
|
||||||
|
secrets: Option<ClientSecrets>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Serialize, Deserialize)]
|
||||||
|
pub struct ClientSecrets {
|
||||||
|
id_token: String,
|
||||||
|
access_token: String,
|
||||||
|
refresh_token: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MizePart for ClientAuth {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"client_auth"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClientAuth {
|
||||||
|
pub fn id_token(&self) -> MizeResult<&str> {
|
||||||
|
if self.secrets.is_none() {
|
||||||
|
return Err(mize_err!("Client not logged in"));
|
||||||
|
}
|
||||||
|
Ok(&self.secrets.as_ref().unwrap().id_token)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn access_token(&self) -> MizeResult<&str> {
|
||||||
|
if self.secrets.is_none() {
|
||||||
|
return Err(mize_err!("Client not logged in"));
|
||||||
|
}
|
||||||
|
Ok(&self.secrets.as_ref().unwrap().access_token)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn refresh_token(&self) -> MizeResult<&str> {
|
||||||
|
if self.secrets.is_none() {
|
||||||
|
return Err(mize_err!("Client not logged in"));
|
||||||
|
}
|
||||||
|
Ok(&self.secrets.as_ref().unwrap().refresh_token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn client_auth(mize: &mut Mize) -> MizeResult<()> {
|
||||||
|
let mize_clone = mize.clone();
|
||||||
|
|
||||||
|
let secrets = match read_secrets(mize) {
|
||||||
|
Ok(secrets) => Some(secrets),
|
||||||
|
Err(_) => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut cli = mize.get_part_native::<marts::CliPart>("cli")?;
|
||||||
|
cli.subcommand(Command::new("login"), |_, mut mize| {
|
||||||
|
let secrets = mize.spawn_async_blocking("client_auth", auth_flow(mize_clone))?;
|
||||||
|
println!("hereeeeee oneeeeeeeeee");
|
||||||
|
let mut auth = mize.get_part_native::<ClientAuth>("client_auth")?;
|
||||||
|
println!("hereeeeee two");
|
||||||
|
write_secrets(&mut mize, &secrets)?;
|
||||||
|
auth.secrets = Some(secrets);
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
mize.register_part(Box::new(ClientAuth {
|
||||||
|
secrets,
|
||||||
|
mize: mize.clone(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_secrets(mize: &mut Mize) -> MizeResult<ClientSecrets> {
|
||||||
|
let mize_dir = mize.get_config("data_dir")?.value_string()?;
|
||||||
|
let secrets_file_path = PathBuf::from(mize_dir).join("client_secrets.json");
|
||||||
|
|
||||||
|
let secrets_string = std::fs::read_to_string(secrets_file_path)?;
|
||||||
|
let secrets: ClientSecrets = serde_json::from_str(&secrets_string)?;
|
||||||
|
Ok(secrets)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_secrets(mize: &mut Mize, secrets: &ClientSecrets) -> MizeResult<()> {
|
||||||
|
let mize_dir = mize.get_config("data_dir")?.value_string()?;
|
||||||
|
let secrets_file_path = PathBuf::from(mize_dir).join("client_secrets.json");
|
||||||
|
|
||||||
|
let secrets_string = serde_json::to_string(secrets)?;
|
||||||
|
std::fs::write(secrets_file_path, secrets_string)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct Combined<'a> {
|
||||||
|
code: &'a str,
|
||||||
|
state: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn auth_flow(mut mize: Mize) -> MizeResult<ClientSecrets> {
|
||||||
|
// ===== CONFIG =====
|
||||||
|
// Replace these with your issuer, client id and the public redirect URL served by the axum app.
|
||||||
|
|
||||||
|
let issuer = mize.get_config("auth.client.issuer")?.value_string()?;
|
||||||
|
let client_id = mize.get_config("auth.client.client_id")?.value_string()?;
|
||||||
|
let redirect_url = mize
|
||||||
|
.get_config("auth.client.redirect_url")?
|
||||||
|
.value_string()?;
|
||||||
|
|
||||||
|
let issuer = IssuerUrl::new(issuer)?;
|
||||||
|
let client_id = ClientId::new(client_id);
|
||||||
|
let redirect_uri = RedirectUrl::new(redirect_url)?;
|
||||||
|
|
||||||
|
// Discover provider metadata
|
||||||
|
let provider_metadata =
|
||||||
|
CoreProviderMetadata::discover_async(issuer, &openidconnect::reqwest::Client::new())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let client = CoreClient::from_provider_metadata(
|
||||||
|
provider_metadata,
|
||||||
|
client_id,
|
||||||
|
None, // no client secret for public clients
|
||||||
|
)
|
||||||
|
.set_redirect_uri(redirect_uri);
|
||||||
|
|
||||||
|
// ===== PKCE + state + nonce =====
|
||||||
|
let (pkce_challenge, pkce_verifier) = PkceCodeChallenge::new_random_sha256();
|
||||||
|
let csrf_token = CsrfToken::new_random();
|
||||||
|
let csrf_token_clone = csrf_token.clone();
|
||||||
|
let nonce = Nonce::new_random();
|
||||||
|
|
||||||
|
// Build the authorization URL - include code_challenge and state
|
||||||
|
let (auth_url, _csrf_token_returned, _nonce_returned) = client
|
||||||
|
.authorize_url(
|
||||||
|
CoreAuthenticationFlow::AuthorizationCode,
|
||||||
|
move || csrf_token_clone.clone(),
|
||||||
|
move || nonce.clone(),
|
||||||
|
)
|
||||||
|
.set_pkce_challenge(pkce_challenge)
|
||||||
|
.add_scope(Scope::new("openid".to_string()))
|
||||||
|
.add_scope(Scope::new("profile".to_string()))
|
||||||
|
.url();
|
||||||
|
|
||||||
|
println!("Opening browser to authenticate...");
|
||||||
|
println!(
|
||||||
|
"If your browser does not open automatically, visit:\n\n{}\n",
|
||||||
|
auth_url
|
||||||
|
);
|
||||||
|
|
||||||
|
// Try to open browser (best-effort)
|
||||||
|
if let Err(e) = webbrowser::open(auth_url.as_str()) {
|
||||||
|
eprintln!("Failed to open browser automatically: {}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("When the authorization completes, the web page will show the code (and state).");
|
||||||
|
print!("Paste login string here: ");
|
||||||
|
io::stdout().flush()?;
|
||||||
|
|
||||||
|
// Read user input
|
||||||
|
let mut input = String::new();
|
||||||
|
io::stdin().read_line(&mut input)?;
|
||||||
|
let input = input.trim();
|
||||||
|
|
||||||
|
if input.is_empty() {
|
||||||
|
return Err(mize_err!("No login string provided"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let base64_engine = GeneralPurpose::new(
|
||||||
|
&STANDARD,
|
||||||
|
GeneralPurposeConfig::new().with_decode_padding_mode(DecodePaddingMode::RequireNone),
|
||||||
|
);
|
||||||
|
|
||||||
|
let json_bytes = base64_engine.decode(input)?;
|
||||||
|
let json_str = String::from_utf8(json_bytes)?;
|
||||||
|
let combined: Combined = serde_json::from_str(json_str.as_str())?;
|
||||||
|
|
||||||
|
if combined.state != csrf_token.secret() {
|
||||||
|
return Err(mize_err!(
|
||||||
|
"State mismatch: pasted state does not match expected value"
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
println!("State is valid");
|
||||||
|
};
|
||||||
|
|
||||||
|
// Perform token exchange
|
||||||
|
let token_response = client
|
||||||
|
.exchange_code(AuthorizationCode::new(combined.code.to_string()))?
|
||||||
|
.set_pkce_verifier(PkceCodeVerifier::new(pkce_verifier.secret().to_string()))
|
||||||
|
.request_async(&openidconnect::reqwest::Client::new())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let id_token = token_response
|
||||||
|
.extra_fields()
|
||||||
|
.id_token()
|
||||||
|
.ok_or(mize_err!("no id_token"))?;
|
||||||
|
|
||||||
|
//let refresh = token_response.refresh_token();
|
||||||
|
|
||||||
|
println!("\n=== Token response ===");
|
||||||
|
println!("Access token: {:?}", token_response.access_token().secret());
|
||||||
|
println!("ID token: {}", id_token.to_string());
|
||||||
|
//println!("Refresh token: {}", refresh.secret());
|
||||||
|
|
||||||
|
Ok(ClientSecrets {
|
||||||
|
id_token: id_token.to_string(),
|
||||||
|
access_token: token_response.access_token().secret().to_string(),
|
||||||
|
refresh_token: "".to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -16,3 +16,8 @@ mod website;
|
|||||||
pub use platform::os::server::server;
|
pub use platform::os::server::server;
|
||||||
#[cfg(feature = "target-os")]
|
#[cfg(feature = "target-os")]
|
||||||
pub use platform::os::ui;
|
pub use platform::os::ui;
|
||||||
|
|
||||||
|
pub mod auth {
|
||||||
|
pub mod client;
|
||||||
|
}
|
||||||
|
pub use auth::client::client_auth;
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
export function add(a: number, b: number): number {
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Learn more at https://docs.deno.com/runtime/manual/examples/module_metadata#concepts
|
|
||||||
if (import.meta.main) {
|
|
||||||
console.log("Add 2 + 3 =", add(2, 3));
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { assertEquals } from "@std/assert";
|
|
||||||
import { add } from "./main.ts";
|
|
||||||
|
|
||||||
Deno.test(function addTest() {
|
|
||||||
assertEquals(add(2, 3), 5);
|
|
||||||
});
|
|
||||||
@@ -22,6 +22,7 @@ fn os_main(mize: &mut Mize) -> MizeResult<()> {
|
|||||||
marts::habitica(mize)?;
|
marts::habitica(mize)?;
|
||||||
marts::c2vi(mize)?;
|
marts::c2vi(mize)?;
|
||||||
ppc::server(mize)?;
|
ppc::server(mize)?;
|
||||||
|
ppc::client_auth(mize)?;
|
||||||
|
|
||||||
let mut cli = mize.get_part_native::<marts::CliPart>("cli")?;
|
let mut cli = mize.get_part_native::<marts::CliPart>("cli")?;
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ use axum_oidc::{
|
|||||||
EmptyAdditionalClaims, OidcAuthLayer, OidcClaims, OidcClient, OidcLoginLayer,
|
EmptyAdditionalClaims, OidcAuthLayer, OidcClaims, OidcClient, OidcLoginLayer,
|
||||||
OidcRpInitiatedLogout, error::MiddlewareError,
|
OidcRpInitiatedLogout, error::MiddlewareError,
|
||||||
};
|
};
|
||||||
|
use base64::{
|
||||||
|
Engine,
|
||||||
|
alphabet::STANDARD,
|
||||||
|
engine::{GeneralPurpose, GeneralPurposeConfig},
|
||||||
|
};
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use mize::Mize;
|
use mize::Mize;
|
||||||
@@ -99,7 +104,8 @@ pub async fn start_server(mize: &mut Mize) -> MizeResult<()> {
|
|||||||
.layer(session_layer)
|
.layer(session_layer)
|
||||||
.layer(tower_http::trace::TraceLayer::new_for_http())
|
.layer(tower_http::trace::TraceLayer::new_for_http())
|
||||||
// not authenticated routes
|
// not authenticated routes
|
||||||
.route("/", get(ppc_main_page));
|
.route("/", get(ppc_main_page))
|
||||||
|
.route("/oidc_display_code_and_state", get(display_code_and_state));
|
||||||
|
|
||||||
tracing::info!("Running on http://localhost:3000");
|
tracing::info!("Running on http://localhost:3000");
|
||||||
|
|
||||||
@@ -136,3 +142,55 @@ async fn maybe_authenticated(
|
|||||||
async fn logout(logout: OidcRpInitiatedLogout) -> impl IntoResponse {
|
async fn logout(logout: OidcRpInitiatedLogout) -> impl IntoResponse {
|
||||||
logout.with_post_logout_redirect(Uri::from_static("https://localhost:3000"))
|
logout.with_post_logout_redirect(Uri::from_static("https://localhost:3000"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// src/web_callback.rs
|
||||||
|
use axum::{extract::Query, response::Html};
|
||||||
|
use html_escape::encode_text;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct CallbackParams {
|
||||||
|
pub code: Option<String>,
|
||||||
|
pub state: Option<String>,
|
||||||
|
pub error: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct Combined<'a> {
|
||||||
|
code: &'a str,
|
||||||
|
state: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn display_code_and_state(Query(params): Query<CallbackParams>) -> Html<String> {
|
||||||
|
// Safe fallbacks
|
||||||
|
let code = params.code.clone().unwrap_or_default();
|
||||||
|
let state = params.state.clone().unwrap_or_default();
|
||||||
|
let error = params.error.clone().unwrap_or_default();
|
||||||
|
|
||||||
|
// Create JSON object and base64 encode it
|
||||||
|
let combined = Combined {
|
||||||
|
code: &code,
|
||||||
|
state: &state,
|
||||||
|
};
|
||||||
|
// serde_json::to_string should succeed for simple strings; fallback to empty JSON on error
|
||||||
|
let json = serde_json::to_string(&combined)
|
||||||
|
.unwrap_or_else(|_| "{\"code\":\"\",\"state\":\"\"}".into());
|
||||||
|
let base64_engine = GeneralPurpose::new(
|
||||||
|
&STANDARD,
|
||||||
|
GeneralPurposeConfig::new().with_encode_padding(false),
|
||||||
|
);
|
||||||
|
let b64 = base64_engine.encode(json);
|
||||||
|
|
||||||
|
let b64_escaped = encode_text(&b64);
|
||||||
|
let error_escaped = encode_text(&error);
|
||||||
|
println!("err: {}", error_escaped);
|
||||||
|
println!("b: {}", b64_escaped);
|
||||||
|
|
||||||
|
let html = match error_escaped.as_ref() {
|
||||||
|
"" => format!("Copy this into your client: {}", b64_escaped),
|
||||||
|
_ => format!("An Error occured: {}", error_escaped),
|
||||||
|
};
|
||||||
|
|
||||||
|
Html(html)
|
||||||
|
}
|
||||||
|
|||||||
13
packages/spacetime-module-ppc/Cargo.toml
Normal file
13
packages/spacetime-module-ppc/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "quickstart_chat"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
spacetimedb = "1.11.*"
|
||||||
|
log = "0.4"
|
||||||
36
packages/spacetime-module-ppc/src/lib.rs
Normal file
36
packages/spacetime-module-ppc/src/lib.rs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
use log::*;
|
||||||
|
use spacetimedb::{ReducerContext, Table};
|
||||||
|
|
||||||
|
#[spacetimedb::table(name = person, public)]
|
||||||
|
pub struct CoolPerson {
|
||||||
|
username: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[spacetimedb::reducer(init)]
|
||||||
|
pub fn init(_ctx: &ReducerContext) {
|
||||||
|
// Called when the module is initially published
|
||||||
|
info!("hiiiiiii");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[spacetimedb::reducer(client_connected)]
|
||||||
|
pub fn identity_connected(_ctx: &ReducerContext) {
|
||||||
|
// Called everytime a new client connects
|
||||||
|
}
|
||||||
|
|
||||||
|
#[spacetimedb::reducer(client_disconnected)]
|
||||||
|
pub fn identity_disconnected(_ctx: &ReducerContext) {
|
||||||
|
// Called everytime a client disconnects
|
||||||
|
}
|
||||||
|
|
||||||
|
#[spacetimedb::reducer]
|
||||||
|
pub fn add(ctx: &ReducerContext, username: String) {
|
||||||
|
ctx.db.person().insert(CoolPerson { username });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[spacetimedb::reducer]
|
||||||
|
pub fn say_hello(ctx: &ReducerContext) {
|
||||||
|
for person in ctx.db.person().iter() {
|
||||||
|
log::info!("Hello, {}!", person.username);
|
||||||
|
}
|
||||||
|
log::info!("Hello, World!");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user