diff --git a/Cargo.lock b/Cargo.lock
index 0f6df575c..f6eaa5f69 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,22 +1,16 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-version = 3
+version = 4
[[package]]
name = "addr2line"
-version = "0.22.0"
+version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
+checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
dependencies = [
"gimli",
]
-[[package]]
-name = "adler"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
-
[[package]]
name = "adler2"
version = "2.0.0"
@@ -72,9 +66,9 @@ dependencies = [
[[package]]
name = "allocator-api2"
-version = "0.2.18"
+version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
+checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "android-tzdata"
@@ -93,9 +87,9 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.6.15"
+version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -108,49 +102,50 @@ dependencies = [
[[package]]
name = "anstyle"
-version = "1.0.8"
+version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
-version = "0.2.5"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
-version = "1.1.1"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
- "windows-sys",
+ "windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.4"
+version = "3.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
+checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
dependencies = [
"anstyle",
- "windows-sys",
+ "once_cell",
+ "windows-sys 0.59.0",
]
[[package]]
name = "anyhow"
-version = "1.0.86"
+version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
[[package]]
name = "async-compression"
-version = "0.4.12"
+version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa"
+checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522"
dependencies = [
"brotli",
"flate2",
@@ -162,9 +157,9 @@ dependencies = [
[[package]]
name = "async-stream"
-version = "0.3.5"
+version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
+checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
dependencies = [
"async-stream-impl",
"futures-core",
@@ -173,9 +168,9 @@ dependencies = [
[[package]]
name = "async-stream-impl"
-version = "0.3.5"
+version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
+checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
@@ -184,9 +179,9 @@ dependencies = [
[[package]]
name = "async-trait"
-version = "0.1.82"
+version = "0.1.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1"
+checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056"
dependencies = [
"proc-macro2",
"quote",
@@ -201,9 +196,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]]
name = "attribute-derive"
-version = "0.10.1"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36f18fc482cf559bca9efe778ba2fd0d1c16a31d5d24a2c886ed16b2d217e454"
+checksum = "0053e96dd3bec5b4879c23a138d6ef26f2cb936c9cdc96274ac2b9ed44b5bb54"
dependencies = [
"attribute-derive-macro",
"derive-where",
@@ -215,14 +210,14 @@ dependencies = [
[[package]]
name = "attribute-derive-macro"
-version = "0.10.1"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a85958950e587256a16c72325ff3c4f3e4db25999173e9ca2864665be84ff63b"
+checksum = "463b53ad0fd5b460af4b1915fe045ff4d946d025fb6c4dc3337752eaa980f71b"
dependencies = [
"collection_literals",
"interpolator",
"manyhow",
- "proc-macro-utils 0.10.0",
+ "proc-macro-utils",
"proc-macro2",
"quote",
"quote-use",
@@ -231,9 +226,9 @@ dependencies = [
[[package]]
name = "autocfg"
-version = "1.3.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "axum"
@@ -248,7 +243,7 @@ dependencies = [
"futures-util",
"http 0.2.12",
"http-body 0.4.6",
- "hyper 0.14.30",
+ "hyper 0.14.32",
"itoa",
"matchit",
"memchr",
@@ -258,26 +253,26 @@ dependencies = [
"rustversion",
"serde",
"sync_wrapper 0.1.2",
- "tower",
+ "tower 0.4.13",
"tower-layer",
"tower-service",
]
[[package]]
name = "axum"
-version = "0.7.5"
+version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
+checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
dependencies = [
"async-trait",
- "axum-core 0.4.3",
- "base64 0.21.7",
+ "axum-core 0.4.5",
+ "base64 0.22.1",
"bytes",
"futures-util",
- "http 1.1.0",
+ "http 1.2.0",
"http-body 1.0.1",
"http-body-util",
- "hyper 1.4.1",
+ "hyper 1.5.2",
"hyper-util",
"itoa",
"matchit",
@@ -291,10 +286,10 @@ dependencies = [
"serde_path_to_error",
"serde_urlencoded",
"sha1",
- "sync_wrapper 1.0.1",
+ "sync_wrapper 1.0.2",
"tokio",
- "tokio-tungstenite",
- "tower",
+ "tokio-tungstenite 0.24.0",
+ "tower 0.5.2",
"tower-layer",
"tower-service",
"tracing",
@@ -319,20 +314,20 @@ dependencies = [
[[package]]
name = "axum-core"
-version = "0.4.3"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
+checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
dependencies = [
"async-trait",
"bytes",
"futures-util",
- "http 1.1.0",
+ "http 1.2.0",
"http-body 1.0.1",
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
- "sync_wrapper 0.1.2",
+ "sync_wrapper 1.0.2",
"tower-layer",
"tower-service",
"tracing",
@@ -340,17 +335,17 @@ dependencies = [
[[package]]
name = "backtrace"
-version = "0.3.73"
+version = "0.3.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
+checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
dependencies = [
"addr2line",
- "cc",
"cfg-if",
"libc",
- "miniz_oxide 0.7.4",
+ "miniz_oxide",
"object",
"rustc-demangle",
+ "windows-targets",
]
[[package]]
@@ -380,7 +375,7 @@ version = "0.66.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7"
dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.7.0",
"cexpr",
"clang-sys",
"lazy_static",
@@ -405,9 +400,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.6.0"
+version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be"
[[package]]
name = "block-buffer"
@@ -429,9 +424,9 @@ dependencies = [
[[package]]
name = "brotli"
-version = "6.0.0"
+version = "7.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b"
+checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
@@ -462,9 +457,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
-version = "1.7.1"
+version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
+checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
dependencies = [
"serde",
]
@@ -480,9 +475,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.1.13"
+version = "1.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48"
+checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b"
dependencies = [
"shlex",
]
@@ -502,11 +497,17 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+[[package]]
+name = "cfg_aliases"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+
[[package]]
name = "chrono"
-version = "0.4.38"
+version = "0.4.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
+checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
dependencies = [
"android-tzdata",
"iana-time-zone",
@@ -540,9 +541,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.16"
+version = "4.5.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019"
+checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
dependencies = [
"clap_builder",
"clap_derive",
@@ -550,9 +551,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.15"
+version = "4.5.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6"
+checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
dependencies = [
"anstream",
"anstyle",
@@ -562,9 +563,9 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.5.13"
+version = "4.5.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
+checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
dependencies = [
"heck",
"proc-macro2",
@@ -574,9 +575,9 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "0.7.2"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
+checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "collection_literals"
@@ -586,9 +587,9 @@ checksum = "186dce98367766de751c42c4f03970fc60fc012296e706ccbb9d5df9b6c1e271"
[[package]]
name = "colorchoice"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "console_error_panic_hook"
@@ -600,16 +601,6 @@ dependencies = [
"wasm-bindgen",
]
-[[package]]
-name = "core-foundation"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
-dependencies = [
- "core-foundation-sys",
- "libc",
-]
-
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
@@ -618,9 +609,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "cpufeatures"
-version = "0.2.13"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad"
+checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
dependencies = [
"libc",
]
@@ -716,6 +707,17 @@ dependencies = [
"crypto-common",
]
+[[package]]
+name = "displaydoc"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "dyn-clone"
version = "1.0.17"
@@ -730,9 +732,9 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "encoding_rs"
-version = "0.8.34"
+version = "0.8.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
+checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
dependencies = [
"cfg-if",
]
@@ -745,12 +747,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
-version = "0.3.9"
+version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
- "windows-sys",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -773,12 +775,26 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "flate2"
-version = "1.0.32"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666"
+checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
dependencies = [
"crc32fast",
- "miniz_oxide 0.8.0",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "flexi_logger"
+version = "0.28.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cca927478b3747ba47f98af6ba0ac0daea4f12d12f55e9104071b3dc00276310"
+dependencies = [
+ "chrono",
+ "glob",
+ "log",
+ "nu-ansi-term 0.50.1",
+ "regex",
+ "thiserror 1.0.69",
]
[[package]]
@@ -802,14 +818,14 @@ version = "0.1.0"
dependencies = [
"anyhow",
"async-trait",
- "axum 0.7.5",
+ "axum 0.7.9",
"bytes",
"clap",
"fpx-lib",
"fpx-macros",
"futures-util",
"hex",
- "http 1.1.0",
+ "http 1.2.0",
"http-body-util",
"include_dir",
"libsql",
@@ -818,7 +834,7 @@ dependencies = [
"opentelemetry-otlp",
"opentelemetry-proto",
"opentelemetry_sdk",
- "prost 0.13.2",
+ "prost 0.13.4",
"rand",
"reqwest",
"schemars",
@@ -827,13 +843,13 @@ dependencies = [
"serde_with",
"strum",
"test-log",
- "thiserror",
+ "thiserror 2.0.11",
"time",
"tokio",
- "tokio-tungstenite",
+ "tokio-tungstenite 0.21.0",
"toml",
- "tonic 0.12.2",
- "tower",
+ "tonic 0.12.3",
+ "tower 0.4.13",
"tracing",
"tracing-opentelemetry",
"tracing-subscriber",
@@ -846,26 +862,26 @@ version = "0.1.0"
dependencies = [
"anyhow",
"async-trait",
- "axum 0.7.5",
+ "axum 0.7.9",
"bytes",
"fpx-macros",
"futures-util",
"hex",
- "http 1.1.0",
+ "http 1.2.0",
"http-body-util",
"libsql",
"opentelemetry",
"opentelemetry-proto",
"opentelemetry_sdk",
- "prost 0.13.2",
+ "prost 0.13.4",
"schemars",
"serde",
"serde_json",
"strum",
- "thiserror",
+ "thiserror 2.0.11",
"time",
"tokio",
- "tower",
+ "tower 0.4.13",
"tower-http 0.5.2",
"tracing",
"tracing-opentelemetry",
@@ -887,7 +903,7 @@ dependencies = [
name = "fpx-workers"
version = "0.1.0"
dependencies = [
- "axum 0.7.5",
+ "axum 0.7.9",
"console_error_panic_hook",
"fpx-lib",
"getrandom",
@@ -905,9 +921,9 @@ dependencies = [
[[package]]
name = "futures"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
+checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
dependencies = [
"futures-channel",
"futures-core",
@@ -920,9 +936,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
+checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
"futures-core",
"futures-sink",
@@ -930,15 +946,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
+checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-executor"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
+checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
dependencies = [
"futures-core",
"futures-task",
@@ -947,15 +963,15 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
+checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
[[package]]
name = "futures-macro"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
+checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
@@ -964,21 +980,21 @@ dependencies = [
[[package]]
name = "futures-sink"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
+checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
[[package]]
name = "futures-task"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
+checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]]
name = "futures-util"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
+checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-channel",
"futures-core",
@@ -1017,15 +1033,15 @@ dependencies = [
[[package]]
name = "gimli"
-version = "0.29.0"
+version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "glob"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
[[package]]
name = "h2"
@@ -1039,7 +1055,7 @@ dependencies = [
"futures-sink",
"futures-util",
"http 0.2.12",
- "indexmap 2.4.0",
+ "indexmap 2.7.0",
"slab",
"tokio",
"tokio-util",
@@ -1048,17 +1064,17 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205"
+checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e"
dependencies = [
"atomic-waker",
"bytes",
"fnv",
"futures-core",
"futures-sink",
- "http 1.1.0",
- "indexmap 2.4.0",
+ "http 1.2.0",
+ "indexmap 2.7.0",
"slab",
"tokio",
"tokio-util",
@@ -1081,6 +1097,12 @@ dependencies = [
"allocator-api2",
]
+[[package]]
+name = "hashbrown"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
+
[[package]]
name = "hashlink"
version = "0.8.4"
@@ -1096,12 +1118,6 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-[[package]]
-name = "hermit-abi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
-
[[package]]
name = "hex"
version = "0.4.3"
@@ -1110,11 +1126,11 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "home"
-version = "0.5.9"
+version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
+checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
dependencies = [
- "windows-sys",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -1130,9 +1146,9 @@ dependencies = [
[[package]]
name = "http"
-version = "1.1.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
+checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea"
dependencies = [
"bytes",
"fnv",
@@ -1157,7 +1173,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
- "http 1.1.0",
+ "http 1.2.0",
]
[[package]]
@@ -1168,7 +1184,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
dependencies = [
"bytes",
"futures-util",
- "http 1.1.0",
+ "http 1.2.0",
"http-body 1.0.1",
"pin-project-lite",
]
@@ -1181,9 +1197,9 @@ checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f"
[[package]]
name = "httparse"
-version = "1.9.4"
+version = "1.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
+checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
[[package]]
name = "httpdate"
@@ -1193,9 +1209,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
-version = "0.14.30"
+version = "0.14.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9"
+checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7"
dependencies = [
"bytes",
"futures-channel",
@@ -1217,15 +1233,15 @@ dependencies = [
[[package]]
name = "hyper"
-version = "1.4.1"
+version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05"
+checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
- "h2 0.4.6",
- "http 1.1.0",
+ "h2 0.4.7",
+ "http 1.2.0",
"http-body 1.0.1",
"httparse",
"httpdate",
@@ -1238,36 +1254,18 @@ dependencies = [
[[package]]
name = "hyper-rustls"
-version = "0.25.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "399c78f9338483cb7e630c8474b07268983c6bd5acee012e4211f9f7bb21b070"
-dependencies = [
- "futures-util",
- "http 0.2.12",
- "hyper 0.14.30",
- "log",
- "rustls 0.22.4",
- "rustls-native-certs",
- "rustls-pki-types",
- "tokio",
- "tokio-rustls 0.25.0",
- "webpki-roots",
-]
-
-[[package]]
-name = "hyper-rustls"
-version = "0.27.2"
+version = "0.27.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155"
+checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
dependencies = [
"futures-util",
- "http 1.1.0",
- "hyper 1.4.1",
+ "http 1.2.0",
+ "hyper 1.5.2",
"hyper-util",
- "rustls 0.23.12",
+ "rustls 0.23.21",
"rustls-pki-types",
"tokio",
- "tokio-rustls 0.26.0",
+ "tokio-rustls 0.26.1",
"tower-service",
"webpki-roots",
]
@@ -1278,7 +1276,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
dependencies = [
- "hyper 0.14.30",
+ "hyper 0.14.32",
"pin-project-lite",
"tokio",
"tokio-io-timeout",
@@ -1286,11 +1284,11 @@ dependencies = [
[[package]]
name = "hyper-timeout"
-version = "0.5.1"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793"
+checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
dependencies = [
- "hyper 1.4.1",
+ "hyper 1.5.2",
"hyper-util",
"pin-project-lite",
"tokio",
@@ -1299,29 +1297,28 @@ dependencies = [
[[package]]
name = "hyper-util"
-version = "0.1.7"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9"
+checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
- "http 1.1.0",
+ "http 1.2.0",
"http-body 1.0.1",
- "hyper 1.4.1",
+ "hyper 1.5.2",
"pin-project-lite",
"socket2",
"tokio",
- "tower",
"tower-service",
"tracing",
]
[[package]]
name = "iana-time-zone"
-version = "0.1.60"
+version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@@ -1340,6 +1337,124 @@ dependencies = [
"cc",
]
+[[package]]
+name = "icu_collections"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_locid_transform_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
+
+[[package]]
+name = "icu_normalizer"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "utf16_iter",
+ "utf8_iter",
+ "write16",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
+
+[[package]]
+name = "icu_properties"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locid_transform",
+ "icu_properties_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
+
+[[package]]
+name = "icu_provider"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_provider_macros",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_provider_macros"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "ident_case"
version = "1.0.1"
@@ -1348,12 +1463,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
-version = "0.5.0"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
+dependencies = [
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
dependencies = [
- "unicode-bidi",
- "unicode-normalization",
+ "icu_normalizer",
+ "icu_properties",
]
[[package]]
@@ -1388,12 +1514,12 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.4.0"
+version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
+checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
dependencies = [
"equivalent",
- "hashbrown 0.14.5",
+ "hashbrown 0.15.2",
"serde",
]
@@ -1415,9 +1541,9 @@ checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8"
[[package]]
name = "ipnet"
-version = "2.9.0"
+version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
+checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708"
[[package]]
name = "is_terminal_polyfill"
@@ -1425,15 +1551,6 @@ version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
-[[package]]
-name = "itertools"
-version = "0.10.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
-dependencies = [
- "either",
-]
-
[[package]]
name = "itertools"
version = "0.12.1"
@@ -1454,9 +1571,9 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.11"
+version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "joinery"
@@ -1466,18 +1583,19 @@ checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5"
[[package]]
name = "js-sys"
-version = "0.3.70"
+version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
+checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
dependencies = [
+ "once_cell",
"wasm-bindgen",
]
[[package]]
name = "lazy_format"
-version = "1.10.0"
+version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b05662be9cd63006934464f935195ae936460edb75de7b9a07e0509795afbdc3"
+checksum = "e479e99b287d578ed5f6cd4c92cdf48db219088adb9c5b14f7c155b71dfba792"
[[package]]
name = "lazy_static"
@@ -1493,15 +1611,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
-version = "0.2.158"
+version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
+checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "libloading"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
+checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
dependencies = [
"cfg-if",
"windows-targets",
@@ -1509,32 +1627,31 @@ dependencies = [
[[package]]
name = "libsql"
-version = "0.5.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc44962384bd2223269a81cd0d4a1683182b7bf0408b1d87e731c43e8c501270"
+checksum = "fe18646e4ef8db446bc3e3f5fb96131483203bc5f4998ff149f79a067530c01c"
dependencies = [
"anyhow",
"async-stream",
"async-trait",
"bincode",
- "bitflags 2.6.0",
+ "bitflags 2.7.0",
"bytes",
"fallible-iterator 0.3.0",
"futures",
"http 0.2.12",
- "hyper 0.14.30",
- "hyper-rustls 0.25.0",
+ "hyper 0.14.32",
"libsql-sqlite3-parser",
"libsql-sys",
"libsql_replication",
"parking_lot",
"serde",
- "thiserror",
+ "thiserror 1.0.69",
"tokio",
"tokio-stream",
"tonic 0.11.0",
"tonic-web",
- "tower",
+ "tower 0.4.13",
"tower-http 0.4.4",
"tracing",
"uuid",
@@ -1543,9 +1660,9 @@ dependencies = [
[[package]]
name = "libsql-ffi"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "906c4fcdba5bced1c034507aeb06fe3082c5674c4199fd850884de5d633b2446"
+checksum = "5f2a50a585a1184a43621a9133b7702ba5cb7a87ca5e704056b19d8005de6faf"
dependencies = [
"bindgen",
"cc",
@@ -1553,11 +1670,11 @@ dependencies = [
[[package]]
name = "libsql-rusqlite"
-version = "0.32.0"
+version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b811f72e13b9864601197d234621ffe89a490b2cb034cf28753b111334cf1db3"
+checksum = "ae65c66088dcd309abbd5617ae046abac2a2ee0a7fdada5127353bd68e0a27ea"
dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.7.0",
"fallible-iterator 0.2.0",
"fallible-streaming-iterator",
"hashlink",
@@ -1571,10 +1688,10 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15a90128c708356af8f7d767c9ac2946692c9112b4f74f07b99a01a60680e413"
dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.7.0",
"cc",
"fallible-iterator 0.3.0",
- "indexmap 2.4.0",
+ "indexmap 2.7.0",
"log",
"memchr",
"phf",
@@ -1585,9 +1702,9 @@ dependencies = [
[[package]]
name = "libsql-sys"
-version = "0.7.0"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce92e8edf5a0dc928c6031ff3cf05794a23570b417254a7f3883b2072ae3b3c3"
+checksum = "5c05b61c226781d6f5e26e3e7364617f19c0c1d5332035802e9229d6024cec05"
dependencies = [
"bytes",
"libsql-ffi",
@@ -1599,9 +1716,9 @@ dependencies = [
[[package]]
name = "libsql_replication"
-version = "0.5.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b107ff45254e35e1b72586ddff84cc4ebaede1e1a59f88bf2a0371321d23f7ae"
+checksum = "9cf40c4c2c01462da758272976de0a23d19b4e9c714db08efecf262d896655b5"
dependencies = [
"aes",
"async-stream",
@@ -1613,7 +1730,7 @@ dependencies = [
"parking_lot",
"prost 0.12.6",
"serde",
- "thiserror",
+ "thiserror 1.0.69",
"tokio",
"tokio-stream",
"tokio-util",
@@ -1625,9 +1742,15 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
-version = "0.4.14"
+version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
+
+[[package]]
+name = "litemap"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
[[package]]
name = "lock_api"
@@ -1641,9 +1764,9 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.22"
+version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
[[package]]
name = "manyhow"
@@ -1663,7 +1786,7 @@ version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495"
dependencies = [
- "proc-macro-utils 0.10.0",
+ "proc-macro-utils",
"proc-macro2",
"quote",
]
@@ -1703,32 +1826,22 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
-dependencies = [
- "adler",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.0"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
+checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
dependencies = [
"adler2",
]
[[package]]
name = "mio"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
+checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [
- "hermit-abi",
"libc",
"wasi",
- "windows-sys",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -1751,6 +1864,15 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "nu-ansi-term"
+version = "0.50.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "num-conv"
version = "0.1.0"
@@ -1768,107 +1890,102 @@ dependencies = [
[[package]]
name = "object"
-version = "0.36.3"
+version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
-version = "1.19.0"
+version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
-
-[[package]]
-name = "openssl-probe"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "opentelemetry"
-version = "0.24.0"
+version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c365a63eec4f55b7efeceb724f1336f26a9cf3427b70e59e2cd2a5b947fba96"
+checksum = "ab70038c28ed37b97d8ed414b6429d343a8bbf44c9f79ec854f3a643029ba6d7"
dependencies = [
"futures-core",
"futures-sink",
"js-sys",
- "once_cell",
"pin-project-lite",
- "thiserror",
+ "thiserror 1.0.69",
+ "tracing",
]
[[package]]
name = "opentelemetry-http"
-version = "0.13.0"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad31e9de44ee3538fb9d64fe3376c1362f406162434609e79aea2a41a0af78ab"
+checksum = "10a8a7f5f6ba7c1b286c2fbca0454eaba116f63bbe69ed250b642d36fbb04d80"
dependencies = [
"async-trait",
"bytes",
- "http 1.1.0",
+ "http 1.2.0",
"opentelemetry",
"reqwest",
]
[[package]]
name = "opentelemetry-otlp"
-version = "0.17.0"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b925a602ffb916fb7421276b86756027b37ee708f9dce2dbdcc51739f07e727"
+checksum = "91cf61a1868dacc576bf2b2a1c3e9ab150af7272909e80085c3173384fe11f76"
dependencies = [
"async-trait",
"futures-core",
- "http 1.1.0",
+ "http 1.2.0",
"opentelemetry",
"opentelemetry-http",
"opentelemetry-proto",
"opentelemetry_sdk",
- "prost 0.13.2",
+ "prost 0.13.4",
"reqwest",
"serde_json",
- "thiserror",
+ "thiserror 1.0.69",
"tokio",
- "tonic 0.12.2",
+ "tonic 0.12.3",
+ "tracing",
]
[[package]]
name = "opentelemetry-proto"
-version = "0.7.0"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30ee9f20bff9c984511a02f082dc8ede839e4a9bf15cc2487c8d6fea5ad850d9"
+checksum = "a6e05acbfada5ec79023c85368af14abd0b307c015e9064d249b2a950ef459a6"
dependencies = [
"hex",
"opentelemetry",
"opentelemetry_sdk",
- "prost 0.13.2",
+ "prost 0.13.4",
"schemars",
"serde",
- "tonic 0.12.2",
+ "tonic 0.12.3",
]
[[package]]
name = "opentelemetry_sdk"
-version = "0.24.1"
+version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "692eac490ec80f24a17828d49b40b60f5aeaccdfe6a503f939713afd22bc28df"
+checksum = "231e9d6ceef9b0b2546ddf52335785ce41252bc7474ee8ba05bfad277be13ab8"
dependencies = [
"async-trait",
"futures-channel",
"futures-executor",
"futures-util",
"glob",
- "once_cell",
"opentelemetry",
"percent-encoding",
"rand",
"serde_json",
- "thiserror",
+ "thiserror 1.0.69",
"tokio",
"tokio-stream",
+ "tracing",
]
[[package]]
@@ -1914,18 +2031,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "phf"
-version = "0.11.2"
+version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
+checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_codegen"
-version = "0.11.2"
+version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
+checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
dependencies = [
"phf_generator",
"phf_shared",
@@ -1933,9 +2050,9 @@ dependencies = [
[[package]]
name = "phf_generator"
-version = "0.11.2"
+version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
+checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared",
"rand",
@@ -1943,9 +2060,9 @@ dependencies = [
[[package]]
name = "phf_shared"
-version = "0.11.2"
+version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
+checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
dependencies = [
"siphasher",
"uncased",
@@ -1953,18 +2070,18 @@ dependencies = [
[[package]]
name = "pin-project"
-version = "1.1.5"
+version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
+checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
-version = "1.1.5"
+version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
+checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb"
dependencies = [
"proc-macro2",
"quote",
@@ -1973,9 +2090,9 @@ dependencies = [
[[package]]
name = "pin-project-lite"
-version = "0.2.14"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
+checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "pin-utils"
@@ -2000,25 +2117,14 @@ dependencies = [
[[package]]
name = "prettyplease"
-version = "0.2.20"
+version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e"
+checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac"
dependencies = [
"proc-macro2",
"syn",
]
-[[package]]
-name = "proc-macro-utils"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f59e109e2f795a5070e69578c4dc101068139f74616778025ae1011d4cd41a8"
-dependencies = [
- "proc-macro2",
- "quote",
- "smallvec",
-]
-
[[package]]
name = "proc-macro-utils"
version = "0.10.0"
@@ -2032,9 +2138,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.86"
+version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
@@ -2051,12 +2157,12 @@ dependencies = [
[[package]]
name = "prost"
-version = "0.13.2"
+version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b2ecbe40f08db5c006b5764a2645f7f3f141ce756412ac9e1dd6087e6d32995"
+checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec"
dependencies = [
"bytes",
- "prost-derive 0.13.2",
+ "prost-derive 0.13.4",
]
[[package]]
@@ -2074,9 +2180,9 @@ dependencies = [
[[package]]
name = "prost-derive"
-version = "0.13.2"
+version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acf0c195eebb4af52c752bec4f52f645da98b6e92077a04110c7f349477ae5ac"
+checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3"
dependencies = [
"anyhow",
"itertools 0.13.0",
@@ -2087,66 +2193,70 @@ dependencies = [
[[package]]
name = "quinn"
-version = "0.11.3"
+version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156"
+checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef"
dependencies = [
"bytes",
"pin-project-lite",
"quinn-proto",
"quinn-udp",
- "rustc-hash 2.0.0",
- "rustls 0.23.12",
+ "rustc-hash 2.1.0",
+ "rustls 0.23.21",
"socket2",
- "thiserror",
+ "thiserror 2.0.11",
"tokio",
"tracing",
]
[[package]]
name = "quinn-proto"
-version = "0.11.8"
+version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6"
+checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d"
dependencies = [
"bytes",
+ "getrandom",
"rand",
"ring",
- "rustc-hash 2.0.0",
- "rustls 0.23.12",
+ "rustc-hash 2.1.0",
+ "rustls 0.23.21",
+ "rustls-pki-types",
"slab",
- "thiserror",
+ "thiserror 2.0.11",
"tinyvec",
"tracing",
+ "web-time",
]
[[package]]
name = "quinn-udp"
-version = "0.5.4"
+version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285"
+checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904"
dependencies = [
+ "cfg_aliases",
"libc",
"once_cell",
"socket2",
"tracing",
- "windows-sys",
+ "windows-sys 0.59.0",
]
[[package]]
name = "quote"
-version = "1.0.37"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "quote-use"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48e96ac59974192a2fa6ee55a41211cf1385c5b2a8636a4c3068b3b3dd599ece"
+checksum = "9619db1197b497a36178cfc736dc96b271fe918875fbf1344c436a7e93d0321e"
dependencies = [
"quote",
"quote-use-macros",
@@ -2154,12 +2264,11 @@ dependencies = [
[[package]]
name = "quote-use-macros"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4c57308e9dde4d7be9af804f6deeaa9951e1de1d5ffce6142eb964750109f7e"
+checksum = "82ebfb7faafadc06a7ab141a6f67bcfb24cb8beb158c6fe933f2f035afa99f35"
dependencies = [
- "derive-where",
- "proc-macro-utils 0.8.0",
+ "proc-macro-utils",
"proc-macro2",
"quote",
"syn",
@@ -2197,23 +2306,23 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.5.3"
+version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
+checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.7.0",
]
[[package]]
name = "regex"
-version = "1.10.6"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
- "regex-automata 0.4.7",
- "regex-syntax 0.8.4",
+ "regex-automata 0.4.9",
+ "regex-syntax 0.8.5",
]
[[package]]
@@ -2227,13 +2336,13 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.7"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
- "regex-syntax 0.8.4",
+ "regex-syntax 0.8.5",
]
[[package]]
@@ -2244,15 +2353,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
-version = "0.8.4"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "reqwest"
-version = "0.12.7"
+version = "0.12.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63"
+checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da"
dependencies = [
"base64 0.22.1",
"bytes",
@@ -2260,12 +2369,12 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-util",
- "h2 0.4.6",
- "http 1.1.0",
+ "h2 0.4.7",
+ "http 1.2.0",
"http-body 1.0.1",
"http-body-util",
- "hyper 1.4.1",
- "hyper-rustls 0.27.2",
+ "hyper 1.5.2",
+ "hyper-rustls",
"hyper-util",
"ipnet",
"js-sys",
@@ -2275,15 +2384,16 @@ dependencies = [
"percent-encoding",
"pin-project-lite",
"quinn",
- "rustls 0.23.12",
+ "rustls 0.23.21",
"rustls-pemfile",
"rustls-pki-types",
"serde",
"serde_json",
"serde_urlencoded",
- "sync_wrapper 1.0.1",
+ "sync_wrapper 1.0.2",
"tokio",
- "tokio-rustls 0.26.0",
+ "tokio-rustls 0.26.1",
+ "tower 0.5.2",
"tower-service",
"url",
"wasm-bindgen",
@@ -2305,7 +2415,7 @@ dependencies = [
"libc",
"spin",
"untrusted",
- "windows-sys",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -2322,21 +2432,21 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc-hash"
-version = "2.0.0"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
+checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
[[package]]
name = "rustix"
-version = "0.38.34"
+version = "0.38.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
+checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6"
dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.7.0",
"errno",
"libc",
"linux-raw-sys",
- "windows-sys",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -2355,9 +2465,9 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.23.12"
+version = "0.23.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044"
+checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8"
dependencies = [
"once_cell",
"ring",
@@ -2367,40 +2477,29 @@ dependencies = [
"zeroize",
]
-[[package]]
-name = "rustls-native-certs"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04182dffc9091a404e0fc069ea5cd60e5b866c3adf881eff99a32d048242dffa"
-dependencies = [
- "openssl-probe",
- "rustls-pemfile",
- "rustls-pki-types",
- "schannel",
- "security-framework",
-]
-
[[package]]
name = "rustls-pemfile"
-version = "2.1.3"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425"
+checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
- "base64 0.22.1",
"rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
-version = "1.8.0"
+version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0"
+checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37"
+dependencies = [
+ "web-time",
+]
[[package]]
name = "rustls-webpki"
-version = "0.102.6"
+version = "0.102.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e"
+checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
dependencies = [
"ring",
"rustls-pki-types",
@@ -2409,9 +2508,9 @@ dependencies = [
[[package]]
name = "rustversion"
-version = "1.0.17"
+version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
+checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]]
name = "ryu"
@@ -2419,15 +2518,6 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
-[[package]]
-name = "schannel"
-version = "0.1.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
-dependencies = [
- "windows-sys",
-]
-
[[package]]
name = "schemars"
version = "0.8.21"
@@ -2458,34 +2548,11 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-[[package]]
-name = "security-framework"
-version = "2.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
-dependencies = [
- "bitflags 2.6.0",
- "core-foundation",
- "core-foundation-sys",
- "libc",
- "security-framework-sys",
-]
-
-[[package]]
-name = "security-framework-sys"
-version = "2.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf"
-dependencies = [
- "core-foundation-sys",
- "libc",
-]
-
[[package]]
name = "serde"
-version = "1.0.209"
+version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
+checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
@@ -2514,9 +2581,9 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.209"
+version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
+checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
@@ -2536,9 +2603,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.127"
+version = "1.0.135"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad"
+checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
dependencies = [
"itoa",
"memchr",
@@ -2558,9 +2625,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
-version = "0.6.7"
+version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
+checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
dependencies = [
"serde",
]
@@ -2579,15 +2646,15 @@ dependencies = [
[[package]]
name = "serde_with"
-version = "3.9.0"
+version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857"
+checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa"
dependencies = [
"base64 0.22.1",
"chrono",
"hex",
"indexmap 1.9.3",
- "indexmap 2.4.0",
+ "indexmap 2.7.0",
"serde",
"serde_derive",
"serde_json",
@@ -2597,9 +2664,9 @@ dependencies = [
[[package]]
name = "serde_with_macros"
-version = "3.9.0"
+version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350"
+checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e"
dependencies = [
"darling",
"proc-macro2",
@@ -2644,9 +2711,9 @@ dependencies = [
[[package]]
name = "siphasher"
-version = "0.3.11"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "slab"
@@ -2665,12 +2732,12 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
-version = "0.5.7"
+version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
+checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
dependencies = [
"libc",
- "windows-sys",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -2679,6 +2746,12 @@ version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
[[package]]
name = "strsim"
version = "0.11.1"
@@ -2715,9 +2788,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
-version = "2.0.77"
+version = "2.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
+checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
dependencies = [
"proc-macro2",
"quote",
@@ -2732,13 +2805,24 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "sync_wrapper"
-version = "1.0.1"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
+checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
dependencies = [
"futures-core",
]
+[[package]]
+name = "synstructure"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "test-log"
version = "0.2.16"
@@ -2762,18 +2846,38 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "1.0.63"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl 1.0.69",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
+dependencies = [
+ "thiserror-impl 2.0.11",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
- "thiserror-impl",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.63"
+version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
+checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
dependencies = [
"proc-macro2",
"quote",
@@ -2792,9 +2896,9 @@ dependencies = [
[[package]]
name = "time"
-version = "0.3.36"
+version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
+checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
dependencies = [
"deranged",
"itoa",
@@ -2814,19 +2918,29 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
-version = "0.2.18"
+version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
+checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
dependencies = [
"num-conv",
"time-core",
]
+[[package]]
+name = "tinystr"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
[[package]]
name = "tinyvec"
-version = "1.8.0"
+version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
+checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8"
dependencies = [
"tinyvec_macros",
]
@@ -2839,9 +2953,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.40.0"
+version = "1.43.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
+checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e"
dependencies = [
"backtrace",
"bytes",
@@ -2852,7 +2966,7 @@ dependencies = [
"signal-hook-registry",
"socket2",
"tokio-macros",
- "windows-sys",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -2867,9 +2981,9 @@ dependencies = [
[[package]]
name = "tokio-macros"
-version = "2.4.0"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
+checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
@@ -2889,20 +3003,19 @@ dependencies = [
[[package]]
name = "tokio-rustls"
-version = "0.26.0"
+version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
+checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
dependencies = [
- "rustls 0.23.12",
- "rustls-pki-types",
+ "rustls 0.23.21",
"tokio",
]
[[package]]
name = "tokio-stream"
-version = "0.1.15"
+version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af"
+checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
dependencies = [
"futures-core",
"pin-project-lite",
@@ -2921,15 +3034,27 @@ dependencies = [
"rustls-pki-types",
"tokio",
"tokio-rustls 0.25.0",
- "tungstenite",
+ "tungstenite 0.21.0",
"webpki-roots",
]
+[[package]]
+name = "tokio-tungstenite"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9"
+dependencies = [
+ "futures-util",
+ "log",
+ "tokio",
+ "tungstenite 0.24.0",
+]
+
[[package]]
name = "tokio-util"
-version = "0.7.11"
+version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
+checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
dependencies = [
"bytes",
"futures-core",
@@ -2961,11 +3086,11 @@ dependencies = [
[[package]]
name = "toml_edit"
-version = "0.22.20"
+version = "0.22.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
+checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
dependencies = [
- "indexmap 2.4.0",
+ "indexmap 2.7.0",
"serde",
"serde_spanned",
"toml_datetime",
@@ -2986,49 +3111,44 @@ dependencies = [
"h2 0.3.26",
"http 0.2.12",
"http-body 0.4.6",
- "hyper 0.14.30",
+ "hyper 0.14.32",
"hyper-timeout 0.4.1",
"percent-encoding",
"pin-project",
"prost 0.12.6",
- "rustls-native-certs",
- "rustls-pemfile",
- "rustls-pki-types",
"tokio",
- "tokio-rustls 0.25.0",
"tokio-stream",
- "tower",
+ "tower 0.4.13",
"tower-layer",
"tower-service",
"tracing",
- "webpki-roots",
]
[[package]]
name = "tonic"
-version = "0.12.2"
+version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6f6ba989e4b2c58ae83d862d3a3e27690b6e3ae630d0deb59f3697f32aa88ad"
+checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52"
dependencies = [
"async-stream",
"async-trait",
- "axum 0.7.5",
+ "axum 0.7.9",
"base64 0.22.1",
"bytes",
- "h2 0.4.6",
- "http 1.1.0",
+ "h2 0.4.7",
+ "http 1.2.0",
"http-body 1.0.1",
"http-body-util",
- "hyper 1.4.1",
- "hyper-timeout 0.5.1",
+ "hyper 1.5.2",
+ "hyper-timeout 0.5.2",
"hyper-util",
"percent-encoding",
"pin-project",
- "prost 0.13.2",
+ "prost 0.13.4",
"socket2",
"tokio",
"tokio-stream",
- "tower",
+ "tower 0.4.13",
"tower-layer",
"tower-service",
"tracing",
@@ -3044,7 +3164,7 @@ dependencies = [
"bytes",
"http 0.2.12",
"http-body 0.4.6",
- "hyper 0.14.30",
+ "hyper 0.14.32",
"pin-project",
"tokio-stream",
"tonic 0.11.0",
@@ -3074,13 +3194,28 @@ dependencies = [
"tracing",
]
+[[package]]
+name = "tower"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "pin-project-lite",
+ "sync_wrapper 1.0.2",
+ "tokio",
+ "tower-layer",
+ "tower-service",
+]
+
[[package]]
name = "tower-http"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140"
dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.7.0",
"bytes",
"futures-core",
"futures-util",
@@ -3088,7 +3223,7 @@ dependencies = [
"http-body 0.4.6",
"http-range-header",
"pin-project-lite",
- "tower",
+ "tower 0.4.13",
"tower-layer",
"tower-service",
"tracing",
@@ -3101,10 +3236,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
dependencies = [
"async-compression",
- "bitflags 2.6.0",
+ "bitflags 2.7.0",
"bytes",
"futures-core",
- "http 1.1.0",
+ "http 1.2.0",
"http-body 1.0.1",
"http-body-util",
"pin-project-lite",
@@ -3128,9 +3263,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
[[package]]
name = "tracing"
-version = "0.1.40"
+version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"log",
"pin-project-lite",
@@ -3140,9 +3275,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
-version = "0.1.27"
+version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
@@ -3151,9 +3286,9 @@ dependencies = [
[[package]]
name = "tracing-core"
-version = "0.1.32"
+version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
dependencies = [
"once_cell",
"valuable",
@@ -3172,9 +3307,9 @@ dependencies = [
[[package]]
name = "tracing-opentelemetry"
-version = "0.25.0"
+version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9784ed4da7d921bc8df6963f8c80a0e4ce34ba6ba76668acadd3edbd985ff3b"
+checksum = "97a971f6058498b5c0f1affa23e7ea202057a7301dbff68e968b2d578bcbd053"
dependencies = [
"js-sys",
"once_cell",
@@ -3190,9 +3325,9 @@ dependencies = [
[[package]]
name = "tracing-serde"
-version = "0.1.3"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1"
+checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
dependencies = [
"serde",
"tracing-core",
@@ -3200,12 +3335,12 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
-version = "0.3.18"
+version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
+checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
"matchers",
- "nu-ansi-term",
+ "nu-ansi-term 0.46.0",
"once_cell",
"regex",
"serde",
@@ -3248,18 +3383,36 @@ dependencies = [
"byteorder",
"bytes",
"data-encoding",
- "http 1.1.0",
+ "http 1.2.0",
"httparse",
"log",
"rand",
"rustls 0.22.4",
"rustls-pki-types",
"sha1",
- "thiserror",
+ "thiserror 1.0.69",
"url",
"utf-8",
]
+[[package]]
+name = "tungstenite"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a"
+dependencies = [
+ "byteorder",
+ "bytes",
+ "data-encoding",
+ "http 1.2.0",
+ "httparse",
+ "log",
+ "rand",
+ "sha1",
+ "thiserror 1.0.69",
+ "utf-8",
+]
+
[[package]]
name = "typenum"
version = "1.17.0"
@@ -3268,17 +3421,19 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "typeshare-core"
-version = "1.9.2"
+version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1690837c33f49fed661770b6df0bfd8e55e9f0f41ce3791e8dca7a1e513f942"
+checksum = "7d51bba568eeb93c42ba20e9f9bbd356dfe9fd619b97ae2c2ecb411ae76630f8"
dependencies = [
- "itertools 0.10.5",
+ "flexi_logger",
+ "itertools 0.12.1",
"joinery",
"lazy_format",
+ "log",
"proc-macro2",
"quote",
"syn",
- "thiserror",
+ "thiserror 1.0.69",
]
[[package]]
@@ -3290,26 +3445,11 @@ dependencies = [
"version_check",
]
-[[package]]
-name = "unicode-bidi"
-version = "0.3.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
-
[[package]]
name = "unicode-ident"
-version = "1.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
-
-[[package]]
-name = "unicode-normalization"
-version = "0.1.23"
+version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
-dependencies = [
- "tinyvec",
-]
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "untrusted"
@@ -3319,9 +3459,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
-version = "2.5.2"
+version = "2.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
+checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
dependencies = [
"form_urlencoded",
"idna",
@@ -3334,6 +3474,18 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
+[[package]]
+name = "utf16_iter"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
[[package]]
name = "utf8parse"
version = "0.2.2"
@@ -3342,9 +3494,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
-version = "1.10.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
+checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4"
dependencies = [
"getrandom",
"serde",
@@ -3379,24 +3531,24 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.93"
+version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
+checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
dependencies = [
"cfg-if",
"once_cell",
+ "rustversion",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.93"
+version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
+checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
dependencies = [
"bumpalo",
"log",
- "once_cell",
"proc-macro2",
"quote",
"syn",
@@ -3405,21 +3557,22 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.43"
+version = "0.4.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed"
+checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61"
dependencies = [
"cfg-if",
"js-sys",
+ "once_cell",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.93"
+version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
+checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -3427,9 +3580,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.93"
+version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
+checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
@@ -3440,15 +3593,18 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.93"
+version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
+checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+dependencies = [
+ "unicode-ident",
+]
[[package]]
name = "wasm-streams"
-version = "0.4.0"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129"
+checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
dependencies = [
"futures-util",
"js-sys",
@@ -3459,9 +3615,9 @@ dependencies = [
[[package]]
name = "web-sys"
-version = "0.3.70"
+version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
+checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -3479,9 +3635,9 @@ dependencies = [
[[package]]
name = "webpki-roots"
-version = "0.26.3"
+version = "0.26.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd"
+checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e"
dependencies = [
"rustls-pki-types",
]
@@ -3568,6 +3724,15 @@ dependencies = [
"windows-targets",
]
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
[[package]]
name = "windows-targets"
version = "0.52.6"
@@ -3634,26 +3799,26 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
-version = "0.6.18"
+version = "0.6.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
+checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a"
dependencies = [
"memchr",
]
[[package]]
name = "worker"
-version = "0.3.4"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3bd73bd2ea409ae91df99293cbed8b892d39c4c0df5039b646be7586df62c6b"
+checksum = "727789ca7eff9733efbea9d0e97779edc1cf1926e98aee7d7d8afe32805458aa"
dependencies = [
"async-trait",
- "axum 0.7.5",
+ "axum 0.7.9",
"bytes",
"chrono",
"futures-channel",
"futures-util",
- "http 1.1.0",
+ "http 1.2.0",
"http-body 1.0.1",
"js-sys",
"matchit",
@@ -3683,16 +3848,16 @@ dependencies = [
"serde",
"serde-wasm-bindgen 0.5.0",
"serde_json",
- "thiserror",
+ "thiserror 1.0.69",
"wasm-bindgen",
"wasm-bindgen-futures",
]
[[package]]
name = "worker-macros"
-version = "0.3.4"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bbf47d65e77652febb28abedac18b317d8dfe4e57f0d8d9998c4e991fca8e23"
+checksum = "7d625c24570ba9207a2617476013335f28a95cbe513e59bb814ffba092a18058"
dependencies = [
"async-trait",
"proc-macro2",
@@ -3706,9 +3871,9 @@ dependencies = [
[[package]]
name = "worker-sys"
-version = "0.3.4"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4fbb72a85a6509e5ac5dcd1361543468be089ff5ea5c932043b6d0aeac7b6a5"
+checksum = "34563340d41016b4381257c5a16b0d2bc590dbe00500ecfbebcaa16f5f85ce90"
dependencies = [
"cfg-if",
"js-sys",
@@ -3716,6 +3881,18 @@ dependencies = [
"web-sys",
]
+[[package]]
+name = "write16"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
+
+[[package]]
+name = "writeable"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
+
[[package]]
name = "xtask"
version = "0.1.0"
@@ -3732,6 +3909,30 @@ dependencies = [
"url",
]
+[[package]]
+name = "yoke"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
[[package]]
name = "zerocopy"
version = "0.7.35"
@@ -3753,8 +3954,51 @@ dependencies = [
"syn",
]
+[[package]]
+name = "zerofrom"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+
+[[package]]
+name = "zerovec"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/biome.jsonc b/biome.jsonc
index e6665dc82..619ff98d5 100644
--- a/biome.jsonc
+++ b/biome.jsonc
@@ -41,7 +41,7 @@
}
},
{
- "include": ["studio"],
+ "include": ["studio", "lilo/lilo-frontend"],
"linter": {
"enabled": true,
"rules": {
@@ -72,7 +72,8 @@
"packages/client-library-otel",
"api",
"honc-code-gen",
- "fp-services"
+ "fp-services",
+ "lilo/lilo-worker"
],
"linter": {
"enabled": true,
@@ -102,10 +103,12 @@
"honc-code-gen/storage/**/*",
// Client library and website related
"dist",
+ "lilo/lilo-frontend/dist",
+ "lilo/lilo-worker/public",
"www/",
".astro",
// ignore all tsconfig.json files
- "tsconfig.json",
+ "tsconfig*.json",
// ignore any test data files
"test-data/*.js",
// fpx-workers build files
diff --git a/deny.toml b/deny.toml
index 66d5f52a9..15bd466d5 100644
--- a/deny.toml
+++ b/deny.toml
@@ -10,7 +10,7 @@ allow = [
"MIT",
"MPL-2.0",
"OpenSSL",
- "Unicode-DFS-2016",
+ "Unicode-3.0",
]
confidence-threshold = 0.8
exceptions = []
diff --git a/examples/python-fastapi/main.py b/examples/python-fastapi/main.py
index c49afff17..1334301a2 100644
--- a/examples/python-fastapi/main.py
+++ b/examples/python-fastapi/main.py
@@ -25,7 +25,7 @@ def read_root():
return {"Hello": "World"}
-@measure(name="loop")
+@measure()
def loop(n: int = 10) -> None:
for i in range(n):
sleep(0.1)
diff --git a/examples/python-fastapi/pyproject.toml b/examples/python-fastapi/pyproject.toml
index 7fc22590c..f7429b894 100644
--- a/examples/python-fastapi/pyproject.toml
+++ b/examples/python-fastapi/pyproject.toml
@@ -6,7 +6,7 @@ readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"fastapi[standard]>=0.115.6",
- "fpxpy>=0.2.0",
+ "fpxpy>=0.3.1",
]
[dependency-groups]
diff --git a/examples/python-fastapi/uv.lock b/examples/python-fastapi/uv.lock
index d33957654..269cfd37e 100644
--- a/examples/python-fastapi/uv.lock
+++ b/examples/python-fastapi/uv.lock
@@ -229,7 +229,7 @@ standard = [
[[package]]
name = "fpxpy"
-version = "0.2.0"
+version = "0.3.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "dataclasses-json" },
@@ -242,9 +242,9 @@ dependencies = [
{ name = "tracing" },
{ name = "types-requests" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/dd/58/30950deeb7a90078d3c6a27aee9d875d71f87b12f178d8fc8d8703edeba2/fpxpy-0.2.0.tar.gz", hash = "sha256:8b27228e37ea14db4813f6ad49843e5c11f5d28bda528c2663fc01a65f2d595c", size = 46579 }
+sdist = { url = "https://files.pythonhosted.org/packages/4b/2b/764293cd7278034664404afb7254878e8b881c159f2ed913d7c82cf869da/fpxpy-0.3.1.tar.gz", hash = "sha256:05cee57eb2c66dc7abf057fce47117a402841da2a29c7c693e54e6df1dcdbe77", size = 48524 }
wheels = [
- { url = "https://files.pythonhosted.org/packages/84/2c/e359a56973ab2ae1dcaadbe9ae1e659c837851bdcca5b450d5208d8bba8d/fpxpy-0.2.0-py3-none-any.whl", hash = "sha256:9125b486d98be11bcf47ba3b4acdd4b5215406bfb63edfbfc59267e1ac9b82b9", size = 10762 },
+ { url = "https://files.pythonhosted.org/packages/86/ed/79b89eaa406fde796c1561ce2940a7c1b6e6e8832fcdc0c6687e9e7110cd/fpxpy-0.3.1-py3-none-any.whl", hash = "sha256:0f973f70eed3e6afb29fa9627df1e3acbf7f979739f0d109512da1a05f63d5de", size = 13293 },
]
[[package]]
@@ -863,7 +863,7 @@ dev = [
[package.metadata]
requires-dist = [
{ name = "fastapi", extras = ["standard"], specifier = ">=0.115.6" },
- { name = "fpxpy", specifier = ">=0.2.0" },
+ { name = "fpxpy", specifier = ">=0.3.1" },
]
[package.metadata.requires-dev]
@@ -1281,61 +1281,66 @@ wheels = [
[[package]]
name = "wrapt"
-version = "1.17.1"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/c8/dd/35c573cc2b4b8d65ea96bba0247d05710f284857d30e2266d1874f1c727d/wrapt-1.17.1.tar.gz", hash = "sha256:16b2fdfa09a74a3930175b6d9d7d008022aa72a4f02de2b3eecafcc1adfd3cfe", size = 55552 }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/77/0e/eef574fecca770280e610ea0152e6c66cd2c8f15ad286664f52a513dac13/wrapt-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9176057c60438c2ce2284cdefc2b3ee5eddc8c87cd6e24c558d9f5c64298fa4a", size = 38491 },
- { url = "https://files.pythonhosted.org/packages/80/df/b4f2f1cdcf0ca3828269bc796f5a00665c57f34dd0143fdf1db454e272f1/wrapt-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e0f0e731e0ca1583befd3af71b9f90d64ded1535da7b80181cb9e907cc10bbae", size = 38778 },
- { url = "https://files.pythonhosted.org/packages/e7/9c/374e0e8df9eb380d154fe42797ccbd5b695dba097f247b6f70af6f8db51a/wrapt-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:144ed42a4ec3aca5d6f1524f99ee49493bbd0d9c66c24da7ec44b4661dca4dcc", size = 83309 },
- { url = "https://files.pythonhosted.org/packages/07/ba/6a2d5cbee201f77d56952794372ae6e87d07f53bb54762e080b73e3fda4b/wrapt-1.17.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8a7b0699a381226d81d75b48ea58414beb5891ba8982bdc8e42912f766de074", size = 74945 },
- { url = "https://files.pythonhosted.org/packages/d6/fe/41318449af7d90661624aa782f9fc706667de94220d5d9ee064e54a63489/wrapt-1.17.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b20fcef5a3ee410671a5a59472e1ff9dda21cfbe5dfd15e23ee4b99ac455c8e", size = 82777 },
- { url = "https://files.pythonhosted.org/packages/9d/84/cff9bb331050b2880b1d1a85c5eb19e8946e06db2d4ccca2308cf76ae037/wrapt-1.17.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b9a58a1cbdc0588ed4c8ab0c191002d5d831a58c3bad88523fe471ea97eaf57d", size = 81713 },
- { url = "https://files.pythonhosted.org/packages/c4/03/73fad97a2dd1924808fc644908cc6a235d3db2beda276264c1257251a4cf/wrapt-1.17.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:50bbfa7a92da7540426c774e09d6901e44d8f9b513b276ebae03ae244f0c6dbf", size = 74545 },
- { url = "https://files.pythonhosted.org/packages/20/a9/65036eb74d7ae12ea9b2cd05f0906d94496597ae6a4a1b31b50c360cef79/wrapt-1.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:09f5141599eaf36d6cc0b760ad87c2ab6b8618d009b2922639266676775a73a6", size = 81331 },
- { url = "https://files.pythonhosted.org/packages/22/a7/4bb4c832f715c0a3967ff0e87a06717ac284e83742ccc29e2c9fc6c16115/wrapt-1.17.1-cp310-cp310-win32.whl", hash = "sha256:589f24449fd58508533c4a69b2a0f45e9e3419b86b43a0607e2fdb989c6f2552", size = 36425 },
- { url = "https://files.pythonhosted.org/packages/f3/de/4951b171f3db3fc5ed65345c133f6afc36d6108858bd3dda9223b218a17a/wrapt-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:7eca3a1afa9820785b79cb137c68ca38c2f77cfedc3120115da42e1d5800907e", size = 38779 },
- { url = "https://files.pythonhosted.org/packages/68/51/868dde1acc33b010068600ee9b92bc9f7fbdf3dcca8fc8341e66efe1eecb/wrapt-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:da0d0c1c4bd55f9ace919454776dbf0821f537b9a77f739f0c3e34b14728b3b3", size = 38492 },
- { url = "https://files.pythonhosted.org/packages/6d/7f/7586a6b0fc29b9a145d4ff712e05cca7319e03f11bc8160da2c65efcef80/wrapt-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cd7649f0c493d35f9aad9790bbecd7b6fd2e2f7141f6cb1e1e9bb7a681d6d0a4", size = 38773 },
- { url = "https://files.pythonhosted.org/packages/c3/32/ab1f6ec2c691576614d3f290e5d7c2a435ba38c529186beed17a66f71e9f/wrapt-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0aad4f54b3155d673a5c4706a71a0a84f3d415b2fc8a2a399a964d70f18846a2", size = 83775 },
- { url = "https://files.pythonhosted.org/packages/fc/4f/34cefb08717f2ba781da57fab09c53ab9737b9e0df5745167af3180d3955/wrapt-1.17.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ebea3ebb6a394f50f150a52e279508e91c8770625ac8fcb5d8cf35995a320f2", size = 75418 },
- { url = "https://files.pythonhosted.org/packages/42/ee/a6bd5e48448239b9acd1bbcc157239f68e801e34e543419f015c050a2773/wrapt-1.17.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53e2986a65eba7c399d7ad1ccd204562d4ffe6e937344fe5a49eb5a83858f797", size = 83199 },
- { url = "https://files.pythonhosted.org/packages/bf/32/f78e4939b80cae4ab15d88b365c1c0f942ae1517608480001b08c8626a84/wrapt-1.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:67c30d3fe245adb0eb1061a0e526905970a0dabe7c5fba5078e0ee9d19f28167", size = 82304 },
- { url = "https://files.pythonhosted.org/packages/34/a4/2fbce8654c321c9412caf84e49cfab7666d1a3c87d78da840a63679f64f0/wrapt-1.17.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6fd88935b12b59a933ef45facb57575095f205d30d0ae8dd1a3b485bc4fa2fbd", size = 75022 },
- { url = "https://files.pythonhosted.org/packages/65/0d/b2038b8616fc24ddc018a1c5c34b2e7c01e43c7fdfa359a0a60d012ae44b/wrapt-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec3e763e7ca8dcba0792fc3e8ff7061186f59e9aafe4438e6bb1f635a6ab0901", size = 81878 },
- { url = "https://files.pythonhosted.org/packages/b4/a2/847059124a480e5ca13f967d12eef2f0e557d80fe4b80c68a6b3f86a78ff/wrapt-1.17.1-cp311-cp311-win32.whl", hash = "sha256:d792631942a102d6d4f71e4948aceb307310ac0a0af054be6d28b4f79583e0f1", size = 36417 },
- { url = "https://files.pythonhosted.org/packages/cc/ae/22452abc6e1f6a4fd847ca75962d1666f4a3b8c8a0bc2f1e9f5e71b7519a/wrapt-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:3dfd4738a630eddfcb7ff6c8e9fe863df3821f9c991dec73821e05450074ae09", size = 38773 },
- { url = "https://files.pythonhosted.org/packages/ea/40/7fb607aa889b107ab7417f633f1893f48be4fd8bd12ec89c6355d26560a8/wrapt-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b1a4c8edd038fee0ce67bf119b16eaa45d22a52bbaf7d0a17d2312eb0003b1bb", size = 38820 },
- { url = "https://files.pythonhosted.org/packages/ce/24/9e8b8b670c5ebab2c05e51ad7403c5317985c53071d0ce4bb85684b9dce1/wrapt-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:181a844005c9818792212a32e004cb4c6bd8e35cae8e97b1a39a1918d95cef58", size = 38921 },
- { url = "https://files.pythonhosted.org/packages/d7/00/c07c9893e6761ee60d59ec319b33b2d3c5b68da674cbbf8ebf6c54cba146/wrapt-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21ffcf16f5c243a626b0f8da637948e3d5984e3bc0c1bc500ad990e88e974e3b", size = 88720 },
- { url = "https://files.pythonhosted.org/packages/d6/09/d3962a902a6be1d5a66b04ec10189618796a5a9b3fb87d0873294661289d/wrapt-1.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb33799b7582bb73787b9903b70595f8eff67eecc9455f668ed01adf53f9eea", size = 80899 },
- { url = "https://files.pythonhosted.org/packages/e2/fc/92d37def794c3626fb3c3aa112aa629544ba21f6c565034dae0e587f03c0/wrapt-1.17.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57e932ad1908b53e9ad67a746432f02bc8473a9ee16e26a47645a2b224fba5fd", size = 89222 },
- { url = "https://files.pythonhosted.org/packages/cd/4f/e0921cb71ed320508cbcf0e450449642c4b892f64bc5b2696ca725427dea/wrapt-1.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b8bd35c15bc82c5cbe397e8196fa57a17ce5d3f30e925a6fd39e4c5bb02fdcff", size = 86707 },
- { url = "https://files.pythonhosted.org/packages/85/16/f61d6afe9c3c9932f8699a62e4e594bcac87fdffc7dbd8f603939c44cfa5/wrapt-1.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:93018dbb956e0ad99ea2fa2c3c22f033549dcb1f56ad9f4555dfe25e49688c5d", size = 79685 },
- { url = "https://files.pythonhosted.org/packages/95/1d/a1940ce270fa7793044e7131d48528b7d4a6ab2e038142a7c82d722aa5c1/wrapt-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5bd9186d52cf3d36bf1823be0e85297e4dbad909bc6dd495ce0d272806d84a7", size = 87568 },
- { url = "https://files.pythonhosted.org/packages/f0/ca/d1292891bfdda05a77b0bdc2ecdca4a9484b02d64a65e2afddfcb5ac17e1/wrapt-1.17.1-cp312-cp312-win32.whl", hash = "sha256:d609f0ab0603bbcbf2de906b366b9f9bec75c32b4493550a940de658cc2ce512", size = 36672 },
- { url = "https://files.pythonhosted.org/packages/63/0f/0d52bff5074392586eb754609bc0877cea5340a2152f946166002b70ed07/wrapt-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:2c160bb8815787646b27a0c8575a26a4d6bf6abd7c5eb250ad3f2d38b29cb2cb", size = 38866 },
- { url = "https://files.pythonhosted.org/packages/0e/16/82d25dd10e97eabb561d491487ff111ac272a4024f40df098bd61c96840b/wrapt-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:99e544e6ce26f89ad5acc6f407bc4daf7c1d42321e836f5c768f834100bdf35c", size = 38821 },
- { url = "https://files.pythonhosted.org/packages/08/e2/c79dd3c9712988156ea86cd507a81f2b3f045eb84af2d0f7aedb42c709f9/wrapt-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:78da796b74f2c8e0af021ee99feb3bff7cb46f8e658fe25c20e66be1080db4a2", size = 38920 },
- { url = "https://files.pythonhosted.org/packages/4d/d8/bc2bb9797543b31ef7311074583c83addbfc21f1bead66ca7c9d637de6fd/wrapt-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f1bc359f6c52e53565e7af24b423e7a1eea97d155f38ac9e90e95303514710b", size = 88691 },
- { url = "https://files.pythonhosted.org/packages/e7/d3/8d64b5ced10eb0ef856ae864c806292de4891c4945db3444188d45a17b43/wrapt-1.17.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cbead724daa13cae46e8ab3bb24938d8514d123f34345535b184f3eb1b7ad717", size = 80862 },
- { url = "https://files.pythonhosted.org/packages/65/22/ee8e9a7014f7c011edac4a9babea4d0aa73a363dd618afc9b31669e478a8/wrapt-1.17.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdf7b0e3d3713331c0bb9daac47cd10e5aa60d060e53696f50de4e560bd5617f", size = 89174 },
- { url = "https://files.pythonhosted.org/packages/fd/10/3d1610d0c220a9f09317d7c9c216889b9dd67329e23d2fcf1017f2d67fc9/wrapt-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f17e8d926f63aed65ff949682c922f96d00f65c2e852c24272232313fa7823d5", size = 86721 },
- { url = "https://files.pythonhosted.org/packages/3c/c1/2f4b20057afcfbfad4886138a702ae2ffd79abbb43884b31e2388895e367/wrapt-1.17.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9e04f3bd30e0b23c0ca7e1d4084e7d28b6d7d2feb8b7bc69b496fe881280579b", size = 79761 },
- { url = "https://files.pythonhosted.org/packages/f2/c9/c6bde0a10a7108da0ffaa0a8337221e66636199b367e7d6f1d035e0b306a/wrapt-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5660e470edfa15ae7ef407272c642d29e9962777a6b30bfa8fc0da2173dc9afd", size = 87586 },
- { url = "https://files.pythonhosted.org/packages/2a/ad/956a2db1196bde82088f5576eb1d7a290c4ffc0dec00bfc9d29fca440fff/wrapt-1.17.1-cp313-cp313-win32.whl", hash = "sha256:a992f9e019145e84616048556546edeaba68e05e1c1ffbe8391067a63cdadb0c", size = 36678 },
- { url = "https://files.pythonhosted.org/packages/d7/3a/8bf805ab213f7830b5998027ada2a3fae8e93529df7b0c446946d7f8e9e9/wrapt-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:5c2e24ba455af4b0a237a890ea6ed9bafd01fac2c47095f87c53ea3344215d43", size = 38873 },
- { url = "https://files.pythonhosted.org/packages/d7/76/878e3891ea25875608c5075b81240a4060e48eec786ff354b2a5d3eb87f1/wrapt-1.17.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88623fd957ba500d8bb0f7427a76496d99313ca2f9e932481c0882e034cf1add", size = 40060 },
- { url = "https://files.pythonhosted.org/packages/76/4b/fdde9124f6f61a56e1982cd0f7f0bc8fe2ababb876a50da3308e9ea462a0/wrapt-1.17.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:162d5f15bdd3b8037e06540902227ef9e0f298496c0afaadd9e2875851446693", size = 40154 },
- { url = "https://files.pythonhosted.org/packages/17/f2/e3d909ded67bd7d15b7f02f9cb05e111d2fef9499c1dc0f43690391b8c53/wrapt-1.17.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bb82447ddae4e3d9b51f40c494f66e6cbd8fb0e8e8b993678416535c67f9a0d", size = 113469 },
- { url = "https://files.pythonhosted.org/packages/6f/96/2ba3bd9b2d81b139a5784bf997bffc54979b561c272a953af3a69c242e02/wrapt-1.17.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ce4cff3922707048d754e365c4ebf41a3bcbf29b329349bf85d51873c7c7e9e", size = 101207 },
- { url = "https://files.pythonhosted.org/packages/eb/9a/c8e0275eeef83f0b8bf685034244fb0bf21d2e759fd7a6d54005de6b887f/wrapt-1.17.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fdc4e73a3fa0c25eed4d836d9732226f0326957cb075044a7f252b465299433", size = 109341 },
- { url = "https://files.pythonhosted.org/packages/4b/e3/346259c335b04d342beddba6a97030932b53a8ae35d7ff8a319ab2204270/wrapt-1.17.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:bca1c0824f824bcd97b4b179dd55dcad1dab419252be2b2faebbcacefa3b27b2", size = 110232 },
- { url = "https://files.pythonhosted.org/packages/c3/aa/9611db2f50359b0b091e501405bc2497b7369185b342cae7bb2218a986e8/wrapt-1.17.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:6d44b14f3a2f6343a07c90344850b7af5515538ce3a5d01f9c87d8bae9bd8724", size = 100474 },
- { url = "https://files.pythonhosted.org/packages/33/c2/edbcad020deeb742bce83647a7d13e47c35fafcab4fba4a89ec006ad0385/wrapt-1.17.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:169033329022739c6f0d8cd3031a113953b0ba500f3d5978904bdd40baec4568", size = 106377 },
- { url = "https://files.pythonhosted.org/packages/4f/bf/e2aa032cea63737cbabd4069c86d6aa4ba075ee19c44a165e1362a5b403b/wrapt-1.17.1-cp313-cp313t-win32.whl", hash = "sha256:52f0907287d9104112dbebda46af4db0793fcc4c64c8a867099212d116b6db64", size = 37987 },
- { url = "https://files.pythonhosted.org/packages/77/fb/439f032c1b52a1750c304ff85253edfec3a50d4e39fa9a338ab0f837acb4/wrapt-1.17.1-cp313-cp313t-win_amd64.whl", hash = "sha256:7966f98fa36933333d8a1c3d8552aa3d0735001901a4aabcfbd5a502b4ef14fe", size = 40751 },
- { url = "https://files.pythonhosted.org/packages/94/47/299f204e352655c117b9dec03fc585866df7eea72660515208ec67c185c4/wrapt-1.17.1-py3-none-any.whl", hash = "sha256:f3117feb1fc479eaf84b549d3f229d5d2abdb823f003bc2a1c6dd70072912fa0", size = 23589 },
+version = "1.17.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/fc/e91cc220803d7bc4db93fb02facd8461c37364151b8494762cc88b0fbcef/wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", size = 55531 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5a/d1/1daec934997e8b160040c78d7b31789f19b122110a75eca3d4e8da0049e1/wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984", size = 53307 },
+ { url = "https://files.pythonhosted.org/packages/1b/7b/13369d42651b809389c1a7153baa01d9700430576c81a2f5c5e460df0ed9/wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22", size = 38486 },
+ { url = "https://files.pythonhosted.org/packages/62/bf/e0105016f907c30b4bd9e377867c48c34dc9c6c0c104556c9c9126bd89ed/wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7", size = 38777 },
+ { url = "https://files.pythonhosted.org/packages/27/70/0f6e0679845cbf8b165e027d43402a55494779295c4b08414097b258ac87/wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c", size = 83314 },
+ { url = "https://files.pythonhosted.org/packages/0f/77/0576d841bf84af8579124a93d216f55d6f74374e4445264cb378a6ed33eb/wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72", size = 74947 },
+ { url = "https://files.pythonhosted.org/packages/90/ec/00759565518f268ed707dcc40f7eeec38637d46b098a1f5143bff488fe97/wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061", size = 82778 },
+ { url = "https://files.pythonhosted.org/packages/f8/5a/7cffd26b1c607b0b0c8a9ca9d75757ad7620c9c0a9b4a25d3f8a1480fafc/wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2", size = 81716 },
+ { url = "https://files.pythonhosted.org/packages/7e/09/dccf68fa98e862df7e6a60a61d43d644b7d095a5fc36dbb591bbd4a1c7b2/wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c", size = 74548 },
+ { url = "https://files.pythonhosted.org/packages/b7/8e/067021fa3c8814952c5e228d916963c1115b983e21393289de15128e867e/wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62", size = 81334 },
+ { url = "https://files.pythonhosted.org/packages/4b/0d/9d4b5219ae4393f718699ca1c05f5ebc0c40d076f7e65fd48f5f693294fb/wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563", size = 36427 },
+ { url = "https://files.pythonhosted.org/packages/72/6a/c5a83e8f61aec1e1aeef939807602fb880e5872371e95df2137142f5c58e/wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f", size = 38774 },
+ { url = "https://files.pythonhosted.org/packages/cd/f7/a2aab2cbc7a665efab072344a8949a71081eed1d2f451f7f7d2b966594a2/wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58", size = 53308 },
+ { url = "https://files.pythonhosted.org/packages/50/ff/149aba8365fdacef52b31a258c4dc1c57c79759c335eff0b3316a2664a64/wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda", size = 38488 },
+ { url = "https://files.pythonhosted.org/packages/65/46/5a917ce85b5c3b490d35c02bf71aedaa9f2f63f2d15d9949cc4ba56e8ba9/wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438", size = 38776 },
+ { url = "https://files.pythonhosted.org/packages/ca/74/336c918d2915a4943501c77566db41d1bd6e9f4dbc317f356b9a244dfe83/wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a", size = 83776 },
+ { url = "https://files.pythonhosted.org/packages/09/99/c0c844a5ccde0fe5761d4305485297f91d67cf2a1a824c5f282e661ec7ff/wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000", size = 75420 },
+ { url = "https://files.pythonhosted.org/packages/b4/b0/9fc566b0fe08b282c850063591a756057c3247b2362b9286429ec5bf1721/wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6", size = 83199 },
+ { url = "https://files.pythonhosted.org/packages/9d/4b/71996e62d543b0a0bd95dda485219856def3347e3e9380cc0d6cf10cfb2f/wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b", size = 82307 },
+ { url = "https://files.pythonhosted.org/packages/39/35/0282c0d8789c0dc9bcc738911776c762a701f95cfe113fb8f0b40e45c2b9/wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662", size = 75025 },
+ { url = "https://files.pythonhosted.org/packages/4f/6d/90c9fd2c3c6fee181feecb620d95105370198b6b98a0770cba090441a828/wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72", size = 81879 },
+ { url = "https://files.pythonhosted.org/packages/8f/fa/9fb6e594f2ce03ef03eddbdb5f4f90acb1452221a5351116c7c4708ac865/wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317", size = 36419 },
+ { url = "https://files.pythonhosted.org/packages/47/f8/fb1773491a253cbc123c5d5dc15c86041f746ed30416535f2a8df1f4a392/wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3", size = 38773 },
+ { url = "https://files.pythonhosted.org/packages/a1/bd/ab55f849fd1f9a58ed7ea47f5559ff09741b25f00c191231f9f059c83949/wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", size = 53799 },
+ { url = "https://files.pythonhosted.org/packages/53/18/75ddc64c3f63988f5a1d7e10fb204ffe5762bc663f8023f18ecaf31a332e/wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", size = 38821 },
+ { url = "https://files.pythonhosted.org/packages/48/2a/97928387d6ed1c1ebbfd4efc4133a0633546bec8481a2dd5ec961313a1c7/wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", size = 38919 },
+ { url = "https://files.pythonhosted.org/packages/73/54/3bfe5a1febbbccb7a2f77de47b989c0b85ed3a6a41614b104204a788c20e/wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", size = 88721 },
+ { url = "https://files.pythonhosted.org/packages/25/cb/7262bc1b0300b4b64af50c2720ef958c2c1917525238d661c3e9a2b71b7b/wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", size = 80899 },
+ { url = "https://files.pythonhosted.org/packages/2a/5a/04cde32b07a7431d4ed0553a76fdb7a61270e78c5fd5a603e190ac389f14/wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", size = 89222 },
+ { url = "https://files.pythonhosted.org/packages/09/28/2e45a4f4771fcfb109e244d5dbe54259e970362a311b67a965555ba65026/wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", size = 86707 },
+ { url = "https://files.pythonhosted.org/packages/c6/d2/dcb56bf5f32fcd4bd9aacc77b50a539abdd5b6536872413fd3f428b21bed/wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", size = 79685 },
+ { url = "https://files.pythonhosted.org/packages/80/4e/eb8b353e36711347893f502ce91c770b0b0929f8f0bed2670a6856e667a9/wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", size = 87567 },
+ { url = "https://files.pythonhosted.org/packages/17/27/4fe749a54e7fae6e7146f1c7d914d28ef599dacd4416566c055564080fe2/wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", size = 36672 },
+ { url = "https://files.pythonhosted.org/packages/15/06/1dbf478ea45c03e78a6a8c4be4fdc3c3bddea5c8de8a93bc971415e47f0f/wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", size = 38865 },
+ { url = "https://files.pythonhosted.org/packages/ce/b9/0ffd557a92f3b11d4c5d5e0c5e4ad057bd9eb8586615cdaf901409920b14/wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", size = 53800 },
+ { url = "https://files.pythonhosted.org/packages/c0/ef/8be90a0b7e73c32e550c73cfb2fa09db62234227ece47b0e80a05073b375/wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", size = 38824 },
+ { url = "https://files.pythonhosted.org/packages/36/89/0aae34c10fe524cce30fe5fc433210376bce94cf74d05b0d68344c8ba46e/wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", size = 38920 },
+ { url = "https://files.pythonhosted.org/packages/3b/24/11c4510de906d77e0cfb5197f1b1445d4fec42c9a39ea853d482698ac681/wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8", size = 88690 },
+ { url = "https://files.pythonhosted.org/packages/71/d7/cfcf842291267bf455b3e266c0c29dcb675b5540ee8b50ba1699abf3af45/wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6", size = 80861 },
+ { url = "https://files.pythonhosted.org/packages/d5/66/5d973e9f3e7370fd686fb47a9af3319418ed925c27d72ce16b791231576d/wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc", size = 89174 },
+ { url = "https://files.pythonhosted.org/packages/a7/d3/8e17bb70f6ae25dabc1aaf990f86824e4fd98ee9cadf197054e068500d27/wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2", size = 86721 },
+ { url = "https://files.pythonhosted.org/packages/6f/54/f170dfb278fe1c30d0ff864513cff526d624ab8de3254b20abb9cffedc24/wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b", size = 79763 },
+ { url = "https://files.pythonhosted.org/packages/4a/98/de07243751f1c4a9b15c76019250210dd3486ce098c3d80d5f729cba029c/wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504", size = 87585 },
+ { url = "https://files.pythonhosted.org/packages/f9/f0/13925f4bd6548013038cdeb11ee2cbd4e37c30f8bfd5db9e5a2a370d6e20/wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a", size = 36676 },
+ { url = "https://files.pythonhosted.org/packages/bf/ae/743f16ef8c2e3628df3ddfd652b7d4c555d12c84b53f3d8218498f4ade9b/wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845", size = 38871 },
+ { url = "https://files.pythonhosted.org/packages/3d/bc/30f903f891a82d402ffb5fda27ec1d621cc97cb74c16fea0b6141f1d4e87/wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192", size = 56312 },
+ { url = "https://files.pythonhosted.org/packages/8a/04/c97273eb491b5f1c918857cd26f314b74fc9b29224521f5b83f872253725/wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b", size = 40062 },
+ { url = "https://files.pythonhosted.org/packages/4e/ca/3b7afa1eae3a9e7fefe499db9b96813f41828b9fdb016ee836c4c379dadb/wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0", size = 40155 },
+ { url = "https://files.pythonhosted.org/packages/89/be/7c1baed43290775cb9030c774bc53c860db140397047cc49aedaf0a15477/wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306", size = 113471 },
+ { url = "https://files.pythonhosted.org/packages/32/98/4ed894cf012b6d6aae5f5cc974006bdeb92f0241775addad3f8cd6ab71c8/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb", size = 101208 },
+ { url = "https://files.pythonhosted.org/packages/ea/fd/0c30f2301ca94e655e5e057012e83284ce8c545df7661a78d8bfca2fac7a/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681", size = 109339 },
+ { url = "https://files.pythonhosted.org/packages/75/56/05d000de894c4cfcb84bcd6b1df6214297b8089a7bd324c21a4765e49b14/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6", size = 110232 },
+ { url = "https://files.pythonhosted.org/packages/53/f8/c3f6b2cf9b9277fb0813418e1503e68414cd036b3b099c823379c9575e6d/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6", size = 100476 },
+ { url = "https://files.pythonhosted.org/packages/a7/b1/0bb11e29aa5139d90b770ebbfa167267b1fc548d2302c30c8f7572851738/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f", size = 106377 },
+ { url = "https://files.pythonhosted.org/packages/6a/e1/0122853035b40b3f333bbb25f1939fc1045e21dd518f7f0922b60c156f7c/wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555", size = 37986 },
+ { url = "https://files.pythonhosted.org/packages/09/5e/1655cf481e079c1f22d0cabdd4e51733679932718dc23bf2db175f329b76/wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", size = 40750 },
+ { url = "https://files.pythonhosted.org/packages/2d/82/f56956041adef78f849db6b289b282e72b55ab8045a75abad81898c28d19/wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", size = 23594 },
]
[[package]]
diff --git a/fp-services/package.json b/fp-services/package.json
index f73919121..dd4b14cfb 100644
--- a/fp-services/package.json
+++ b/fp-services/package.json
@@ -38,7 +38,7 @@
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@cloudflare/workers-types": "^4.20241112.0",
- "drizzle-kit": "^0.24.2",
+ "drizzle-kit": "^0.30.0",
"wrangler": "^3.91.0"
}
}
diff --git a/fpx-lib/Cargo.toml b/fpx-lib/Cargo.toml
index 7bdb0a5db..6760b837a 100644
--- a/fpx-lib/Cargo.toml
+++ b/fpx-lib/Cargo.toml
@@ -20,10 +20,10 @@ fpx-macros = { version = "0.1.0", path = "../fpx-macros" }
futures-util = { version = "0.3", default-features = false }
hex = { version = "0.4", default-features = false, features = ["alloc"] }
http = { version = "1.1", default-features = false }
-libsql = { version = "0.5", default-features = false, optional = true }
-opentelemetry = { version = "0.24", default-features = false }
-opentelemetry_sdk = { version = "0.24", default-features = false }
-opentelemetry-proto = { version = "0.7", default-features = false, features = [
+libsql = { version = "0.6", default-features = false, optional = true }
+opentelemetry = { version = "0.27", default-features = false }
+opentelemetry_sdk = { version = "0.27", default-features = false }
+opentelemetry-proto = { version = "0.27", default-features = false, features = [
"trace",
"gen-tonic-messages",
"with-serde",
@@ -34,22 +34,22 @@ schemars = { workspace = true, default-features = false, features = ["derive"] }
serde = { version = "1.0", default-features = false, features = ["derive"] }
serde_json = { version = "1.0", default-features = false }
strum = { version = "0.26", default-features = false, features = ["derive"] }
-thiserror = { version = "1.0", default-features = false }
+thiserror = { version = "2.0", default-features = false }
time = { version = "0.3", default-features = false, features = [
"serde-human-readable",
] }
tokio = { version = "1.40", default-features = false }
+tower = { version = "0.4", default-features = false }
tower-http = { version = "0.5", default-features = false, features = [
"compression-br",
"compression-gzip",
"decompression-br",
"decompression-gzip",
] }
-tower = { version = "0.4", default-features = false }
tracing = { version = "0.1", default-features = false, features = [
"attributes",
] }
-tracing-opentelemetry = { version = "0.25", default-features = false }
+tracing-opentelemetry = { version = "0.28", default-features = false }
url = { version = "2.5", default-features = false }
wasm-bindgen = { version = "0.2", default-features = false, optional = true }
diff --git a/fpx-workers/Cargo.toml b/fpx-workers/Cargo.toml
index 64ae398e3..5dd0b9908 100644
--- a/fpx-workers/Cargo.toml
+++ b/fpx-workers/Cargo.toml
@@ -34,6 +34,6 @@ tracing-subscriber = { version = "0.3", default-features = false, features = [
"ansi",
] }
tracing-web = { version = "0.1", default-features = false }
-worker = { version = "0.3", features = ["http", "axum", "d1"] }
-worker-macros = { version = "0.3", features = ["http"] }
wasm-bindgen = { version = "0.2", default-features = false }
+worker = { version = "0.5", features = ["http", "axum", "d1"] }
+worker-macros = { version = "0.5", features = ["http"] }
diff --git a/fpx/Cargo.toml b/fpx/Cargo.toml
index 527751ced..016d47706 100644
--- a/fpx/Cargo.toml
+++ b/fpx/Cargo.toml
@@ -19,29 +19,33 @@ axum = { workspace = true, default-features = false, features = [
"tracing",
"ws",
] }
-clap = { workspace = true, features = ["derive", "env"] }
bytes = { version = "1.6" }
-futures-util = { version = "0.3" }
-fpx-macros = { version = "0.1.0", path = "../fpx-macros" }
+clap = { workspace = true, features = ["derive", "env"] }
fpx-lib = { version = "0.1.0", path = "../fpx-lib", features = ["libsql"] }
+fpx-macros = { version = "0.1.0", path = "../fpx-macros" }
+futures-util = { version = "0.3" }
hex = { version = "0.4" }
http = { version = "1.1" }
http-body-util = { version = "0.1" }
include_dir = { version = "0.7.3" }
-libsql = { version = "0.5", default-features = false, features = ["core", "serde"] }
+libsql = { version = "0.6", default-features = false, features = [
+ "core",
+ "serde",
+] }
once_cell = { version = "1.19" }
-opentelemetry = { version = "0.24" }
-opentelemetry_sdk = { version = "0.24", features = ["rt-tokio"] }
-opentelemetry-otlp = { version = "0.17", features = [
+opentelemetry = { version = "0.27" }
+opentelemetry_sdk = { version = "0.27", features = ["rt-tokio"] }
+opentelemetry-otlp = { version = "0.27", features = [
"http-json",
"reqwest-client",
"reqwest-rustls-webpki-roots",
] }
-opentelemetry-proto = { version = "0.7", features = [
+opentelemetry-proto = { version = "0.27", features = [
"gen-tonic-messages",
"with-serde",
"with-schemars",
] }
+prost = { version = "0.13" }
rand = { version = "0.8.5" }
reqwest = { version = "0.12", default-features = false, features = [
"charset",
@@ -52,9 +56,9 @@ reqwest = { version = "0.12", default-features = false, features = [
schemars = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
-strum = { version = "0.26", features = ["derive"] }
serde_with = { version = "3.8.1" }
-thiserror = { version = "1.0" }
+strum = { version = "0.26", features = ["derive"] }
+thiserror = { version = "2.0" }
time = { version = "0.3.17", features = ["serde-human-readable"] }
tokio = { version = "1.40", features = ["rt-multi-thread", "signal", "fs"] }
tokio-tungstenite = { version = "0.21", features = [
@@ -64,13 +68,16 @@ toml = { version = "0.8" }
tonic = { version = "0.12" }
tower = { version = "0.4" }
tracing = { version = "0.1" }
-tracing-opentelemetry = { version = "0.25" }
+tracing-opentelemetry = { version = "0.28" }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
url = { version = "2.5" }
-prost = { version = "0.13" }
[target.'cfg(windows)'.dependencies]
-libsql = { version = "0.5", default-features = false, features = ["core", "serde", "replication"] }
+libsql = { version = "0.6", default-features = false, features = [
+ "core",
+ "serde",
+ "replication",
+] }
[dev-dependencies]
test-log = { version = "0.2", default-features = false, features = ["trace"] }
diff --git a/fpx/src/main.rs b/fpx/src/main.rs
index 7e80f330c..57fb823a3 100644
--- a/fpx/src/main.rs
+++ b/fpx/src/main.rs
@@ -2,8 +2,7 @@ use anyhow::{Context, Result};
use clap::Parser;
use opentelemetry::trace::TracerProvider;
use opentelemetry::KeyValue;
-use opentelemetry_otlp::WithExportConfig;
-use opentelemetry_sdk::trace::Config;
+use opentelemetry_otlp::{SpanExporter, WithExportConfig};
use opentelemetry_sdk::{runtime, Resource};
use std::env;
use std::path::PathBuf;
@@ -45,20 +44,16 @@ fn setup_tracing(args: &commands::Args) -> Result<()> {
let log_layer = tracing_subscriber::fmt::layer();
let trace_layer = if args.enable_tracing {
+ let exporter = SpanExporter::builder()
+ .with_tonic()
+ .with_endpoint(args.otlp_endpoint.to_string())
+ .build()?;
+
// This tracer is responsible for sending the actual traces.
- let tracer_provider = opentelemetry_otlp::new_pipeline()
- .tracing()
- .with_exporter(
- opentelemetry_otlp::new_exporter()
- .tonic()
- .with_endpoint(args.otlp_endpoint.to_string()),
- )
- .with_trace_config(
- Config::default()
- .with_resource(Resource::new(vec![KeyValue::new("service.name", "fpx")])),
- )
- .install_batch(runtime::Tokio)
- .context("unable to install tracer")?;
+ let tracer_provider = opentelemetry_sdk::trace::TracerProvider::builder()
+ .with_resource(Resource::new(vec![KeyValue::new("service.name", "fpx")]))
+ .with_batch_exporter(exporter, runtime::Tokio)
+ .build();
opentelemetry::global::set_tracer_provider(tracer_provider.clone());
diff --git a/fpxpy/pyproject.toml b/fpxpy/pyproject.toml
index c17ca5538..14d1d93eb 100644
--- a/fpxpy/pyproject.toml
+++ b/fpxpy/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "fpxpy"
-version = "0.3.0"
+version = "0.3.1"
authors = [
{ name = "Fiberplane", email = "support@fiberplane.com" },
{ name = "mellowagain", email = "py@mari.zip" },
diff --git a/fpxpy/src/fpxpy/JSONSpanExporter.py b/fpxpy/src/fpxpy/JSONSpanExporter.py
index ee80b70ba..299d9fff5 100644
--- a/fpxpy/src/fpxpy/JSONSpanExporter.py
+++ b/fpxpy/src/fpxpy/JSONSpanExporter.py
@@ -1,7 +1,6 @@
"""Implementation of the JSON Span Exporter"""
from dataclasses import dataclass
-from .logger import logger
from typing import Any, List, Optional
import requests
@@ -11,6 +10,8 @@
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
from opentelemetry.trace import Link, SpanKind, Status
+from .logger import logger
+
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass
diff --git a/fpxpy/src/fpxpy/logger.py b/fpxpy/src/fpxpy/logger.py
index c5fb70199..0185a1992 100644
--- a/fpxpy/src/fpxpy/logger.py
+++ b/fpxpy/src/fpxpy/logger.py
@@ -1,5 +1,6 @@
import logging
-from typing import List, Optional, Callable
+from typing import Callable, Optional
+
from opentelemetry.trace import get_current_span
logger = logging.getLogger("fpxpy")
@@ -8,10 +9,6 @@
class LogSnooper(logging.Handler):
"""Snoop on log messages by storing them in a list"""
- def __init__(self):
- super().__init__()
- self.messages: List[str] = []
-
def emit(self, record: logging.LogRecord) -> None:
span = get_current_span()
diff --git a/fpxpy/src/fpxpy/measure.py b/fpxpy/src/fpxpy/measure.py
index e78a609fa..6bf48cdaf 100644
--- a/fpxpy/src/fpxpy/measure.py
+++ b/fpxpy/src/fpxpy/measure.py
@@ -39,6 +39,18 @@ def measure(
) -> Callable[[Callable[..., Any]], Callable[..., Any]]: ...
+@overload
+def measure(
+ *, # Force named parameters after name
+ span_kind: SpanKind = SpanKind.INTERNAL,
+ on_start: Optional[OnStartCallback[Any]] = None,
+ on_success: Optional[Callable[[Span, Any], None]] = None,
+ on_error: Optional[Callable[[Span, Exception], None]] = None,
+ check_result: Optional[Callable[[Any], None]] = None,
+ attributes: Optional[Attributes] = None,
+) -> Callable[[Callable[..., Any]], Callable[..., Any]]: ...
+
+
@overload
def measure(
name: Optional[str],
diff --git a/fpxpy/src/fpxpy/test_tracing.py b/fpxpy/src/fpxpy/test_tracing.py
index 4d9295d7d..43b012ece 100644
--- a/fpxpy/src/fpxpy/test_tracing.py
+++ b/fpxpy/src/fpxpy/test_tracing.py
@@ -1,17 +1,16 @@
import io
-
+from time import sleep
from typing import List
import pytest
-from time import sleep
from fastapi import FastAPI, HTTPException
from fastapi.testclient import TestClient
-from opentelemetry.sdk.trace.export import SpanExporter
from opentelemetry.sdk.trace import ReadableSpan
+from opentelemetry.sdk.trace.export import SpanExporter
from opentelemetry.trace import SpanKind
-from .tracing import __internal_setup_span_instrumentation
from .measure import measure
+from .tracing import __internal_setup_span_instrumentation
class SpanCollectorExporter(SpanExporter):
diff --git a/fpxpy/src/fpxpy/tracing.py b/fpxpy/src/fpxpy/tracing.py
index d8dab86fd..43107c03b 100644
--- a/fpxpy/src/fpxpy/tracing.py
+++ b/fpxpy/src/fpxpy/tracing.py
@@ -28,10 +28,6 @@
from .measure import measure
from .utils import get_response_attributes, set_request_attributes
-# logger = logging.getLogger()
-# logging.basicConfig(level=logging.INFO)
-# logger = logging.getLogger(__name__)
-
def get_or_set_tracer_provider(service_name: str) -> TracerProvider:
"""
diff --git a/fpxpy/uv.lock b/fpxpy/uv.lock
index f3c783a8a..a9820d129 100644
--- a/fpxpy/uv.lock
+++ b/fpxpy/uv.lock
@@ -174,7 +174,7 @@ wheels = [
[[package]]
name = "fpxpy"
-version = "0.2.1"
+version = "0.3.0"
source = { editable = "." }
dependencies = [
{ name = "dataclasses-json" },
diff --git a/honc-code-gen/package.json b/honc-code-gen/package.json
index 9593efdbf..4586e171e 100644
--- a/honc-code-gen/package.json
+++ b/honc-code-gen/package.json
@@ -54,7 +54,7 @@
"@langchain/langgraph": "^0.2.28",
"ai": "^3.4.33",
"dotenv": "^16.4.7",
- "drizzle-kit": "^0.24.2",
+ "drizzle-kit": "^0.30.0",
"drizzle-orm": "^0.33.0",
"drizzle-zod": "^0.5.1",
"hono": "^4.6.13",
diff --git a/lilo/README.md b/lilo/README.md
new file mode 100644
index 000000000..76d53d442
--- /dev/null
+++ b/lilo/README.md
@@ -0,0 +1,27 @@
+# Lilo
+
+This is a dashboard + external API for "Lilo" - a tool for generating API testing workflows from user stories.
+
+There's more info in each of the `README.md` files in the `lilo-worker` and `lilo-frontend` directories.
+
+For the record:
+
+- `lilo-worker` is the backend, and it has both an internal API and an external API
+- `lilo-frontend` is the dashboard that talks to the internal API, and links to the external API reference (powered by Scalar)
+
+The frontend also imports `hono/client` to talk to the internal API. It also needs to import some types from `lilo-worker`, but it does so in kind of a janky way because I'm not great at configuring separate typescript projects to talk to each other.
+
+## Setup
+
+Run the backend:
+```bash
+cd lilo-worker
+# follow setup instructions
+pnpm dev
+```
+
+Run the frontend:
+```bash
+cd lilo-frontend
+pnpm dev
+```
\ No newline at end of file
diff --git a/lilo/lilo-frontend/.gitignore b/lilo/lilo-frontend/.gitignore
new file mode 100644
index 000000000..a547bf36d
--- /dev/null
+++ b/lilo/lilo-frontend/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/lilo/lilo-frontend/README.md b/lilo/lilo-frontend/README.md
new file mode 100644
index 000000000..c871d8b37
--- /dev/null
+++ b/lilo/lilo-frontend/README.md
@@ -0,0 +1,9 @@
+# Lilo Frontend
+
+This is the frontend for Lilo. It's built with Vite and React.
+
+## HACKS
+
+We need to include `@types/node` and `@cloudflare/workers-types` in the types array in `tsconfig.app.json` because Hono RPC client imports types from it.
+
+I think this means the frontend build will not throw typescript errors when you import node builtins or Cloudflare Workers types. Beware.
diff --git a/lilo/lilo-frontend/biome.jsonc b/lilo/lilo-frontend/biome.jsonc
new file mode 100644
index 000000000..c10e1a975
--- /dev/null
+++ b/lilo/lilo-frontend/biome.jsonc
@@ -0,0 +1,27 @@
+{
+ "$schema": "../../node_modules/@biomejs/biome/configuration_schema.json",
+ "extends": ["../../biome.jsonc"],
+ "files": {
+ "ignore": [
+ "dist",
+ "node_modules",
+ "tsconfig.node.json",
+ "tsconfig.app.json"
+ ]
+ },
+ "overrides": [
+ {
+ "include": ["src"],
+ "linter": {
+ "enabled": true,
+ "rules": {
+ "suspicious": {
+ "noArrayIndexKey": {
+ "level": "off"
+ }
+ }
+ }
+ }
+ }
+ ]
+}
diff --git a/lilo/lilo-frontend/components.json b/lilo/lilo-frontend/components.json
new file mode 100644
index 000000000..37b3ac638
--- /dev/null
+++ b/lilo/lilo-frontend/components.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "default",
+ "rsc": false,
+ "tsx": true,
+ "tailwind": {
+ "config": "tailwind.config.js",
+ "css": "src/index.css",
+ "baseColor": "stone",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ },
+ "iconLibrary": "lucide"
+}
diff --git a/lilo/lilo-frontend/index.html b/lilo/lilo-frontend/index.html
new file mode 100644
index 000000000..6146ba253
--- /dev/null
+++ b/lilo/lilo-frontend/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Lilo
+
+
+
+
+
+
diff --git a/lilo/lilo-frontend/package.json b/lilo/lilo-frontend/package.json
new file mode 100644
index 000000000..586b13190
--- /dev/null
+++ b/lilo/lilo-frontend/package.json
@@ -0,0 +1,43 @@
+{
+ "name": "lilo-frontend",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "format": "biome check . --write",
+ "lint": "biome lint . && pnpm run typecheck",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@radix-ui/react-avatar": "^1.1.1",
+ "@radix-ui/react-dialog": "^1.1.2",
+ "@radix-ui/react-dropdown-menu": "^2.1.2",
+ "@radix-ui/react-label": "^2.1.0",
+ "@radix-ui/react-slot": "^1.1.0",
+ "@radix-ui/react-toast": "^1.2.2",
+ "@tanstack/react-query": "^5.61.5",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "hono": "^4.6.13",
+ "lucide-react": "^0.468.0",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "tailwind-merge": "^2.5.5",
+ "tailwindcss-animate": "^1.0.7"
+ },
+ "devDependencies": {
+ "@cloudflare/workers-types": "^4.20241205.0",
+ "@types/node": "^22.10.2",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
+ "@vitejs/plugin-react": "^4.3.4",
+ "autoprefixer": "^10.4.20",
+ "globals": "^15.12.0",
+ "postcss": "^8.4.49",
+ "tailwindcss": "^3.4.15",
+ "typescript": "~5.6.2",
+ "vite": "^6.0.1"
+ }
+}
diff --git a/lilo/lilo-frontend/postcss.config.js b/lilo/lilo-frontend/postcss.config.js
new file mode 100644
index 000000000..2aa7205d4
--- /dev/null
+++ b/lilo/lilo-frontend/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/lilo/lilo-frontend/public/lilo.svg b/lilo/lilo-frontend/public/lilo.svg
new file mode 100644
index 000000000..852570cf9
--- /dev/null
+++ b/lilo/lilo-frontend/public/lilo.svg
@@ -0,0 +1,20 @@
+
\ No newline at end of file
diff --git a/lilo/lilo-frontend/src/App.tsx b/lilo/lilo-frontend/src/App.tsx
new file mode 100644
index 000000000..eed293bc3
--- /dev/null
+++ b/lilo/lilo-frontend/src/App.tsx
@@ -0,0 +1,71 @@
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { Button } from "./components/ui/button";
+import { Toaster } from "./components/ui/toaster";
+import { LOGOUT_PATH } from "./constants";
+import { useSession } from "./hooks/use-session";
+import { Layout } from "./layout";
+import { DashboardPage } from "./pages/DashboardPage";
+
+const queryClient = new QueryClient();
+
+function AuthContent() {
+ const { data: session, isLoading } = useSession();
+
+ if (isLoading) {
+ return (
+
+
+
+
+ Loading Lilo—Look at Lilo Load!
+
+
+
+ );
+ }
+
+ if (!session) {
+ return (
+
+ );
+ }
+
+ if (!session.user.allowed) {
+ return (
+
+
You are not on the list!
+
Ask Brett to add you to the list
+
+ Log out
+
+
+ );
+ }
+
+ return (
+
+
+
+
+ );
+}
+
+function App() {
+ return (
+
+
+
+ );
+}
+
+export default App;
diff --git a/lilo/lilo-frontend/src/components/ui/avatar.tsx b/lilo/lilo-frontend/src/components/ui/avatar.tsx
new file mode 100644
index 000000000..e87d9aaee
--- /dev/null
+++ b/lilo/lilo-frontend/src/components/ui/avatar.tsx
@@ -0,0 +1,48 @@
+import * as AvatarPrimitive from "@radix-ui/react-avatar";
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Avatar = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+Avatar.displayName = AvatarPrimitive.Root.displayName;
+
+const AvatarImage = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AvatarImage.displayName = AvatarPrimitive.Image.displayName;
+
+const AvatarFallback = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
+
+export { Avatar, AvatarImage, AvatarFallback };
diff --git a/lilo/lilo-frontend/src/components/ui/button.tsx b/lilo/lilo-frontend/src/components/ui/button.tsx
new file mode 100644
index 000000000..1579cf371
--- /dev/null
+++ b/lilo/lilo-frontend/src/components/ui/button.tsx
@@ -0,0 +1,56 @@
+import { Slot } from "@radix-ui/react-slot";
+import { type VariantProps, cva } from "class-variance-authority";
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+ outline:
+ "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-10 px-4 py-2",
+ sm: "h-9 rounded-md px-3",
+ lg: "h-11 rounded-md px-8",
+ icon: "h-10 w-10",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ },
+);
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean;
+}
+
+const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button";
+ return (
+
+ );
+ },
+);
+Button.displayName = "Button";
+
+export { Button, buttonVariants };
diff --git a/lilo/lilo-frontend/src/components/ui/dialog.tsx b/lilo/lilo-frontend/src/components/ui/dialog.tsx
new file mode 100644
index 000000000..f6c203ae6
--- /dev/null
+++ b/lilo/lilo-frontend/src/components/ui/dialog.tsx
@@ -0,0 +1,120 @@
+import * as DialogPrimitive from "@radix-ui/react-dialog";
+import { X } from "lucide-react";
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Dialog = DialogPrimitive.Root;
+
+const DialogTrigger = DialogPrimitive.Trigger;
+
+const DialogPortal = DialogPrimitive.Portal;
+
+const DialogClose = DialogPrimitive.Close;
+
+const DialogOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
+
+const DialogContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+ {children}
+
+
+ Close
+
+
+
+));
+DialogContent.displayName = DialogPrimitive.Content.displayName;
+
+const DialogHeader = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+);
+DialogHeader.displayName = "DialogHeader";
+
+const DialogFooter = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+);
+DialogFooter.displayName = "DialogFooter";
+
+const DialogTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DialogTitle.displayName = DialogPrimitive.Title.displayName;
+
+const DialogDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DialogDescription.displayName = DialogPrimitive.Description.displayName;
+
+export {
+ Dialog,
+ DialogPortal,
+ DialogOverlay,
+ DialogClose,
+ DialogTrigger,
+ DialogContent,
+ DialogHeader,
+ DialogFooter,
+ DialogTitle,
+ DialogDescription,
+};
diff --git a/lilo/lilo-frontend/src/components/ui/dropdown-menu.tsx b/lilo/lilo-frontend/src/components/ui/dropdown-menu.tsx
new file mode 100644
index 000000000..3e594d628
--- /dev/null
+++ b/lilo/lilo-frontend/src/components/ui/dropdown-menu.tsx
@@ -0,0 +1,198 @@
+import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
+import { Check, ChevronRight, Circle } from "lucide-react";
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const DropdownMenu = DropdownMenuPrimitive.Root;
+
+const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
+
+const DropdownMenuGroup = DropdownMenuPrimitive.Group;
+
+const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
+
+const DropdownMenuSub = DropdownMenuPrimitive.Sub;
+
+const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
+
+const DropdownMenuSubTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean;
+ }
+>(({ className, inset, children, ...props }, ref) => (
+
+ {children}
+
+
+));
+DropdownMenuSubTrigger.displayName =
+ DropdownMenuPrimitive.SubTrigger.displayName;
+
+const DropdownMenuSubContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DropdownMenuSubContent.displayName =
+ DropdownMenuPrimitive.SubContent.displayName;
+
+const DropdownMenuContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+
+
+
+));
+DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
+
+const DropdownMenuItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean;
+ }
+>(({ className, inset, ...props }, ref) => (
+
+));
+DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
+
+const DropdownMenuCheckboxItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, checked, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+));
+DropdownMenuCheckboxItem.displayName =
+ DropdownMenuPrimitive.CheckboxItem.displayName;
+
+const DropdownMenuRadioItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+));
+DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
+
+const DropdownMenuLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean;
+ }
+>(({ className, inset, ...props }, ref) => (
+
+));
+DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
+
+const DropdownMenuSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
+
+const DropdownMenuShortcut = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => {
+ return (
+
+ );
+};
+DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
+
+export {
+ DropdownMenu,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+ DropdownMenuRadioItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuGroup,
+ DropdownMenuPortal,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
+ DropdownMenuRadioGroup,
+};
diff --git a/lilo/lilo-frontend/src/components/ui/input.tsx b/lilo/lilo-frontend/src/components/ui/input.tsx
new file mode 100644
index 000000000..09700f605
--- /dev/null
+++ b/lilo/lilo-frontend/src/components/ui/input.tsx
@@ -0,0 +1,22 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Input = React.forwardRef>(
+ ({ className, type, ...props }, ref) => {
+ return (
+
+ );
+ },
+);
+Input.displayName = "Input";
+
+export { Input };
diff --git a/lilo/lilo-frontend/src/components/ui/label.tsx b/lilo/lilo-frontend/src/components/ui/label.tsx
new file mode 100644
index 000000000..a115d28af
--- /dev/null
+++ b/lilo/lilo-frontend/src/components/ui/label.tsx
@@ -0,0 +1,24 @@
+import * as LabelPrimitive from "@radix-ui/react-label";
+import { type VariantProps, cva } from "class-variance-authority";
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const labelVariants = cva(
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
+);
+
+const Label = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef &
+ VariantProps
+>(({ className, ...props }, ref) => (
+
+));
+Label.displayName = LabelPrimitive.Root.displayName;
+
+export { Label };
diff --git a/lilo/lilo-frontend/src/components/ui/skeleton.tsx b/lilo/lilo-frontend/src/components/ui/skeleton.tsx
new file mode 100644
index 000000000..2cdf440dc
--- /dev/null
+++ b/lilo/lilo-frontend/src/components/ui/skeleton.tsx
@@ -0,0 +1,15 @@
+import { cn } from "@/lib/utils";
+
+function Skeleton({
+ className,
+ ...props
+}: React.HTMLAttributes) {
+ return (
+
+ );
+}
+
+export { Skeleton };
diff --git a/lilo/lilo-frontend/src/components/ui/table.tsx b/lilo/lilo-frontend/src/components/ui/table.tsx
new file mode 100644
index 000000000..73cf6b4ad
--- /dev/null
+++ b/lilo/lilo-frontend/src/components/ui/table.tsx
@@ -0,0 +1,117 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Table = React.forwardRef<
+ HTMLTableElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+Table.displayName = "Table";
+
+const TableHeader = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+TableHeader.displayName = "TableHeader";
+
+const TableBody = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+TableBody.displayName = "TableBody";
+
+const TableFooter = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+ tr]:last:border-b-0",
+ className,
+ )}
+ {...props}
+ />
+));
+TableFooter.displayName = "TableFooter";
+
+const TableRow = React.forwardRef<
+ HTMLTableRowElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+TableRow.displayName = "TableRow";
+
+const TableHead = React.forwardRef<
+ HTMLTableCellElement,
+ React.ThHTMLAttributes
+>(({ className, ...props }, ref) => (
+ |
+));
+TableHead.displayName = "TableHead";
+
+const TableCell = React.forwardRef<
+ HTMLTableCellElement,
+ React.TdHTMLAttributes
+>(({ className, ...props }, ref) => (
+ |
+));
+TableCell.displayName = "TableCell";
+
+const TableCaption = React.forwardRef<
+ HTMLTableCaptionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+TableCaption.displayName = "TableCaption";
+
+export {
+ Table,
+ TableHeader,
+ TableBody,
+ TableFooter,
+ TableHead,
+ TableRow,
+ TableCell,
+ TableCaption,
+};
diff --git a/lilo/lilo-frontend/src/components/ui/textarea.tsx b/lilo/lilo-frontend/src/components/ui/textarea.tsx
new file mode 100644
index 000000000..55ede4a74
--- /dev/null
+++ b/lilo/lilo-frontend/src/components/ui/textarea.tsx
@@ -0,0 +1,22 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Textarea = React.forwardRef<
+ HTMLTextAreaElement,
+ React.ComponentProps<"textarea">
+>(({ className, ...props }, ref) => {
+ return (
+
+ );
+});
+Textarea.displayName = "Textarea";
+
+export { Textarea };
diff --git a/lilo/lilo-frontend/src/components/ui/toast.tsx b/lilo/lilo-frontend/src/components/ui/toast.tsx
new file mode 100644
index 000000000..abfbd9f7e
--- /dev/null
+++ b/lilo/lilo-frontend/src/components/ui/toast.tsx
@@ -0,0 +1,127 @@
+import * as ToastPrimitives from "@radix-ui/react-toast";
+import { type VariantProps, cva } from "class-variance-authority";
+import { X } from "lucide-react";
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const ToastProvider = ToastPrimitives.Provider;
+
+const ToastViewport = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
+
+const toastVariants = cva(
+ "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
+ {
+ variants: {
+ variant: {
+ default: "border bg-background text-foreground",
+ destructive:
+ "destructive group border-destructive bg-destructive text-destructive-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ },
+);
+
+const Toast = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef &
+ VariantProps
+>(({ className, variant, ...props }, ref) => {
+ return (
+
+ );
+});
+Toast.displayName = ToastPrimitives.Root.displayName;
+
+const ToastAction = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+ToastAction.displayName = ToastPrimitives.Action.displayName;
+
+const ToastClose = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+));
+ToastClose.displayName = ToastPrimitives.Close.displayName;
+
+const ToastTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+ToastTitle.displayName = ToastPrimitives.Title.displayName;
+
+const ToastDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+ToastDescription.displayName = ToastPrimitives.Description.displayName;
+
+type ToastProps = React.ComponentPropsWithoutRef;
+
+type ToastActionElement = React.ReactElement;
+
+export {
+ type ToastProps,
+ type ToastActionElement,
+ ToastProvider,
+ ToastViewport,
+ Toast,
+ ToastTitle,
+ ToastDescription,
+ ToastClose,
+ ToastAction,
+};
diff --git a/lilo/lilo-frontend/src/components/ui/toaster.tsx b/lilo/lilo-frontend/src/components/ui/toaster.tsx
new file mode 100644
index 000000000..5568131e4
--- /dev/null
+++ b/lilo/lilo-frontend/src/components/ui/toaster.tsx
@@ -0,0 +1,29 @@
+import {
+ Toast,
+ ToastClose,
+ ToastDescription,
+ ToastProvider,
+ ToastTitle,
+ ToastViewport,
+} from "@/components/ui/toast";
+import { useToast } from "@/hooks/use-toast";
+
+export function Toaster() {
+ const { toasts } = useToast();
+
+ return (
+
+ {toasts.map(({ id, title, description, action, ...props }) => (
+
+
+ {title && {title}}
+ {description && {description}}
+
+ {action}
+
+
+ ))}
+
+
+ );
+}
diff --git a/lilo/lilo-frontend/src/constants.ts b/lilo/lilo-frontend/src/constants.ts
new file mode 100644
index 000000000..7f9e37fba
--- /dev/null
+++ b/lilo/lilo-frontend/src/constants.ts
@@ -0,0 +1,2 @@
+export const LOGOUT_PATH = "/auth/logout";
+export const LOGIN_PATH = "/auth/github";
diff --git a/lilo/lilo-frontend/src/hooks/use-session.ts b/lilo/lilo-frontend/src/hooks/use-session.ts
new file mode 100644
index 000000000..de9b8a37a
--- /dev/null
+++ b/lilo/lilo-frontend/src/hooks/use-session.ts
@@ -0,0 +1,23 @@
+import { useQuery } from "@tanstack/react-query";
+import { hc } from "hono/client";
+import type { DashboardAuthClient } from "../../../lilo-worker/src/routes/internal/auth";
+
+async function fetchSession() {
+ const client = hc("/auth");
+ const res = await client.session.$get();
+ if (!res.ok) {
+ throw new Error("Not authenticated");
+ }
+ const user = await res.json();
+ return {
+ user,
+ };
+}
+
+export function useSession() {
+ return useQuery({
+ queryKey: ["session"],
+ queryFn: () => fetchSession(),
+ retry: false,
+ });
+}
diff --git a/lilo/lilo-frontend/src/hooks/use-toast.ts b/lilo/lilo-frontend/src/hooks/use-toast.ts
new file mode 100644
index 000000000..164d2119f
--- /dev/null
+++ b/lilo/lilo-frontend/src/hooks/use-toast.ts
@@ -0,0 +1,197 @@
+"use client";
+
+// Inspired by react-hot-toast library
+import * as React from "react";
+
+import type { ToastActionElement, ToastProps } from "@/components/ui/toast";
+import { useEffect } from "react";
+
+const TOAST_LIMIT = 1;
+const TOAST_REMOVE_DELAY = 1000000;
+
+type ToasterToast = ToastProps & {
+ id: string;
+ title?: React.ReactNode;
+ description?: React.ReactNode;
+ action?: ToastActionElement;
+};
+
+const actionTypes = {
+ ADD_TOAST: "ADD_TOAST",
+ UPDATE_TOAST: "UPDATE_TOAST",
+ DISMISS_TOAST: "DISMISS_TOAST",
+ REMOVE_TOAST: "REMOVE_TOAST",
+} as const;
+
+let count = 0;
+
+function genId() {
+ count = (count + 1) % Number.MAX_SAFE_INTEGER;
+ return count.toString();
+}
+
+type ActionType = typeof actionTypes;
+
+type Action =
+ | {
+ type: ActionType["ADD_TOAST"];
+ toast: ToasterToast;
+ }
+ | {
+ type: ActionType["UPDATE_TOAST"];
+ toast: Partial;
+ }
+ | {
+ type: ActionType["DISMISS_TOAST"];
+ toastId?: ToasterToast["id"];
+ }
+ | {
+ type: ActionType["REMOVE_TOAST"];
+ toastId?: ToasterToast["id"];
+ };
+
+interface State {
+ toasts: ToasterToast[];
+}
+
+const toastTimeouts = new Map>();
+
+const addToRemoveQueue = (toastId: string) => {
+ if (toastTimeouts.has(toastId)) {
+ return;
+ }
+
+ const timeout = setTimeout(() => {
+ toastTimeouts.delete(toastId);
+ dispatch({
+ type: "REMOVE_TOAST",
+ toastId: toastId,
+ });
+ }, TOAST_REMOVE_DELAY);
+
+ toastTimeouts.set(toastId, timeout);
+};
+
+export const reducer = (state: State, action: Action): State => {
+ switch (action.type) {
+ case "ADD_TOAST":
+ return {
+ ...state,
+ toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
+ };
+
+ case "UPDATE_TOAST":
+ return {
+ ...state,
+ toasts: state.toasts.map((t) =>
+ t.id === action.toast.id ? { ...t, ...action.toast } : t,
+ ),
+ };
+
+ case "DISMISS_TOAST": {
+ const { toastId } = action;
+
+ // ! Side effects ! - This could be extracted into a dismissToast() action,
+ // but I'll keep it here for simplicity
+ if (toastId) {
+ addToRemoveQueue(toastId);
+ } else {
+ // biome-ignore lint/complexity/noForEach: shadcn component
+ state.toasts.forEach((toast) => {
+ addToRemoveQueue(toast.id);
+ });
+ }
+
+ return {
+ ...state,
+ toasts: state.toasts.map((t) =>
+ t.id === toastId || toastId === undefined
+ ? {
+ ...t,
+ open: false,
+ }
+ : t,
+ ),
+ };
+ }
+ case "REMOVE_TOAST":
+ if (action.toastId === undefined) {
+ return {
+ ...state,
+ toasts: [],
+ };
+ }
+ return {
+ ...state,
+ toasts: state.toasts.filter((t) => t.id !== action.toastId),
+ };
+ }
+};
+
+const listeners: Array<(state: State) => void> = [];
+
+let memoryState: State = { toasts: [] };
+
+function dispatch(action: Action) {
+ memoryState = reducer(memoryState, action);
+ // biome-ignore lint/complexity/noForEach: shadcn component
+ listeners.forEach((listener) => {
+ listener(memoryState);
+ });
+}
+
+type Toast = Omit;
+
+function toast({ ...props }: Toast) {
+ const id = genId();
+
+ const update = (props: ToasterToast) =>
+ dispatch({
+ type: "UPDATE_TOAST",
+ toast: { ...props, id },
+ });
+ const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
+
+ dispatch({
+ type: "ADD_TOAST",
+ toast: {
+ ...props,
+ id,
+ open: true,
+ onOpenChange: (open) => {
+ if (!open) {
+ dismiss();
+ }
+ },
+ },
+ });
+
+ return {
+ id: id,
+ dismiss,
+ update,
+ };
+}
+
+function useToast() {
+ const [state, setState] = React.useState(memoryState);
+
+ // biome-ignore lint/correctness/useExhaustiveDependencies: shadcn component - seems intentional
+ useEffect(() => {
+ listeners.push(setState);
+ return () => {
+ const index = listeners.indexOf(setState);
+ if (index > -1) {
+ listeners.splice(index, 1);
+ }
+ };
+ }, [state]);
+
+ return {
+ ...state,
+ toast,
+ dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
+ };
+}
+
+export { useToast, toast };
diff --git a/lilo/lilo-frontend/src/index.css b/lilo/lilo-frontend/src/index.css
new file mode 100644
index 000000000..1e87095c8
--- /dev/null
+++ b/lilo/lilo-frontend/src/index.css
@@ -0,0 +1,138 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+ width: 100%;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
+
+@layer base {
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 20 14.3% 4.1%;
+ --card: 0 0% 100%;
+ --card-foreground: 20 14.3% 4.1%;
+ --popover: 0 0% 100%;
+ --popover-foreground: 20 14.3% 4.1%;
+ --primary: 24 9.8% 10%;
+ --primary-foreground: 60 9.1% 97.8%;
+ --secondary: 60 4.8% 95.9%;
+ --secondary-foreground: 24 9.8% 10%;
+ --muted: 60 4.8% 95.9%;
+ --muted-foreground: 25 5.3% 44.7%;
+ --accent: 60 4.8% 95.9%;
+ --accent-foreground: 24 9.8% 10%;
+ --destructive: 0 84.2% 60.2%;
+ --destructive-foreground: 60 9.1% 97.8%;
+ --border: 20 5.9% 90%;
+ --input: 20 5.9% 90%;
+ --ring: 20 14.3% 4.1%;
+ --chart-1: 12 76% 61%;
+ --chart-2: 173 58% 39%;
+ --chart-3: 197 37% 24%;
+ --chart-4: 43 74% 66%;
+ --chart-5: 27 87% 67%;
+ --radius: 0.5rem;
+ }
+ .dark {
+ --background: 20 14.3% 4.1%;
+ --foreground: 60 9.1% 97.8%;
+ --card: 20 14.3% 4.1%;
+ --card-foreground: 60 9.1% 97.8%;
+ --popover: 20 14.3% 4.1%;
+ --popover-foreground: 60 9.1% 97.8%;
+ --primary: 60 9.1% 97.8%;
+ --primary-foreground: 24 9.8% 10%;
+ --secondary: 12 6.5% 15.1%;
+ --secondary-foreground: 60 9.1% 97.8%;
+ --muted: 12 6.5% 15.1%;
+ --muted-foreground: 24 5.4% 63.9%;
+ --accent: 12 6.5% 15.1%;
+ --accent-foreground: 60 9.1% 97.8%;
+ --destructive: 0 62.8% 30.6%;
+ --destructive-foreground: 60 9.1% 97.8%;
+ --border: 12 6.5% 15.1%;
+ --input: 12 6.5% 15.1%;
+ --ring: 24 5.7% 82.9%;
+ --chart-1: 220 70% 50%;
+ --chart-2: 160 60% 45%;
+ --chart-3: 30 80% 55%;
+ --chart-4: 280 65% 60%;
+ --chart-5: 340 75% 55%;
+ }
+}
+
+@layer base {
+ * {
+ @apply border-border;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
diff --git a/lilo/lilo-frontend/src/layout/Layout.tsx b/lilo/lilo-frontend/src/layout/Layout.tsx
new file mode 100644
index 000000000..67b6d58d6
--- /dev/null
+++ b/lilo/lilo-frontend/src/layout/Layout.tsx
@@ -0,0 +1,36 @@
+import type React from "react";
+import { cn } from "../lib/utils";
+import { UserNav } from "./UserNav";
+
+export function Layout({ children }: { children?: React.ReactNode }) {
+ return (
+
+
+
{children}
+
+
+ );
+}
diff --git a/lilo/lilo-frontend/src/layout/UserNav.tsx b/lilo/lilo-frontend/src/layout/UserNav.tsx
new file mode 100644
index 000000000..7f7bd3f4e
--- /dev/null
+++ b/lilo/lilo-frontend/src/layout/UserNav.tsx
@@ -0,0 +1,58 @@
+import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
+import { Button } from "@/components/ui/button";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { LOGIN_PATH, LOGOUT_PATH } from "@/constants";
+import { useSession } from "@/hooks/use-session";
+
+function signIn() {
+ window.location.href = LOGIN_PATH;
+}
+
+function signOut() {
+ window.location.href = LOGOUT_PATH;
+}
+
+export function UserNav() {
+ const { data: session } = useSession();
+
+ if (!session) {
+ return ;
+ }
+
+ return (
+
+
+
+
+
+
+
+
+ {session.user.githubUsername}
+
+
+ {session.user.email}
+
+
+
+
+ signOut()}>Log out
+
+
+ );
+}
diff --git a/lilo/lilo-frontend/src/layout/index.tsx b/lilo/lilo-frontend/src/layout/index.tsx
new file mode 100644
index 000000000..d312c94fb
--- /dev/null
+++ b/lilo/lilo-frontend/src/layout/index.tsx
@@ -0,0 +1 @@
+export { Layout } from "./Layout";
diff --git a/lilo/lilo-frontend/src/lib/utils.ts b/lilo/lilo-frontend/src/lib/utils.ts
new file mode 100644
index 000000000..365058ceb
--- /dev/null
+++ b/lilo/lilo-frontend/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { type ClassValue, clsx } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/lilo/lilo-frontend/src/main.tsx b/lilo/lilo-frontend/src/main.tsx
new file mode 100644
index 000000000..7d2f22bfa
--- /dev/null
+++ b/lilo/lilo-frontend/src/main.tsx
@@ -0,0 +1,11 @@
+import { StrictMode } from "react";
+import { createRoot } from "react-dom/client";
+import "./index.css";
+import App from "./App.tsx";
+
+// biome-ignore lint/style/noNonNullAssertion: it's vite
+createRoot(document.getElementById("root")!).render(
+
+
+ ,
+);
diff --git a/lilo/lilo-frontend/src/pages/DashboardPage/ApiKeyList/ApiKeyList.tsx b/lilo/lilo-frontend/src/pages/DashboardPage/ApiKeyList/ApiKeyList.tsx
new file mode 100644
index 000000000..ec1aa8613
--- /dev/null
+++ b/lilo/lilo-frontend/src/pages/DashboardPage/ApiKeyList/ApiKeyList.tsx
@@ -0,0 +1,126 @@
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Skeleton } from "@/components/ui/skeleton";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import { useToast } from "@/hooks/use-toast";
+import { TrashIcon } from "lucide-react";
+import { useState } from "react";
+import { useCreateApiKey, useDeleteApiKey, useGetApiKeys } from "./queries";
+
+export function ApiKeyList() {
+ const [newKeyName, setNewKeyName] = useState("");
+ const { toast } = useToast();
+
+ const { data: apiKeys, isLoading } = useGetApiKeys();
+
+ const { mutate: createApiKey } = useCreateApiKey();
+ const { mutate: revokeApiKey } = useDeleteApiKey();
+
+ const generateApiKey = () => {
+ if (!newKeyName) {
+ toast({
+ title: "Error",
+ description: "Please enter a name for the API key",
+ variant: "destructive",
+ });
+ return;
+ }
+
+ createApiKey({ name: newKeyName });
+ setNewKeyName("");
+ };
+
+ if (isLoading) {
+ return ;
+ }
+
+ return (
+
+
API Keys
+
+ setNewKeyName(e.target.value)}
+ />
+
+
+
+
+
+ Name
+ Key
+ Created At
+ Actions
+
+
+
+ {apiKeys?.map((key) => (
+
+ {key.name}
+ {key.token}
+ {new Date(key.createdAt).toLocaleString()}
+
+
+
+
+ ))}
+
+
+
+ );
+}
+
+function ApiKeySkeleton() {
+ return (
+
+
API Keys
+
+
+
+
+
+
+
+ Name
+ Key
+ Created At
+ Actions
+
+
+
+ {[...Array(3)].map((_, index) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/lilo/lilo-frontend/src/pages/DashboardPage/ApiKeyList/index.tsx b/lilo/lilo-frontend/src/pages/DashboardPage/ApiKeyList/index.tsx
new file mode 100644
index 000000000..2da3e79cf
--- /dev/null
+++ b/lilo/lilo-frontend/src/pages/DashboardPage/ApiKeyList/index.tsx
@@ -0,0 +1 @@
+export { ApiKeyList } from "./ApiKeyList";
diff --git a/lilo/lilo-frontend/src/pages/DashboardPage/ApiKeyList/queries.ts b/lilo/lilo-frontend/src/pages/DashboardPage/ApiKeyList/queries.ts
new file mode 100644
index 000000000..01051f676
--- /dev/null
+++ b/lilo/lilo-frontend/src/pages/DashboardPage/ApiKeyList/queries.ts
@@ -0,0 +1,72 @@
+import { useToast } from "@/hooks/use-toast";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+import { hc } from "hono/client";
+import type { ApiKeysRouter } from "../../../../../lilo-worker/src/routes/internal";
+
+const apiKeysClient = hc("/internal/api-keys");
+
+const QUERY_KEY = "api-keys";
+
+export function useGetApiKeys() {
+ return useQuery({
+ queryKey: [QUERY_KEY],
+ // TODO - Add error handling
+ queryFn: () => apiKeysClient.index.$get().then((res) => res.json()),
+ });
+}
+
+export function useDeleteApiKey() {
+ const { toast } = useToast();
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (id: string) =>
+ apiKeysClient[":id"].$delete({
+ param: { id },
+ }),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
+ toast({
+ title: "API Key Revoked",
+ description: "The API key has been revoked successfully.",
+ });
+ },
+ onError: () => {
+ toast({
+ title: "Error",
+ description: "Failed to revoke API key",
+ variant: "destructive",
+ });
+ },
+ });
+}
+
+type CreateApiKeyPayload = {
+ name: string;
+};
+
+export function useCreateApiKey() {
+ const { toast } = useToast();
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (payload: CreateApiKeyPayload) =>
+ apiKeysClient.index.$post({
+ json: payload,
+ }),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
+ toast({
+ title: "API Key Created",
+ description: "Your new API key has been created successfully.",
+ });
+ },
+ onError: () => {
+ toast({
+ title: "Error",
+ description: "Failed to create API key",
+ variant: "destructive",
+ });
+ },
+ });
+}
diff --git a/lilo/lilo-frontend/src/pages/DashboardPage/DashboardPage.tsx b/lilo/lilo-frontend/src/pages/DashboardPage/DashboardPage.tsx
new file mode 100644
index 000000000..b3b804826
--- /dev/null
+++ b/lilo/lilo-frontend/src/pages/DashboardPage/DashboardPage.tsx
@@ -0,0 +1,13 @@
+import { ApiKeyList } from "./ApiKeyList";
+import { ProjectList } from "./ProjectList/ProjectList";
+
+export function DashboardPage() {
+ return (
+
+ );
+}
diff --git a/lilo/lilo-frontend/src/pages/DashboardPage/ProjectList/ProjectList.tsx b/lilo/lilo-frontend/src/pages/DashboardPage/ProjectList/ProjectList.tsx
new file mode 100644
index 000000000..71bbbda8a
--- /dev/null
+++ b/lilo/lilo-frontend/src/pages/DashboardPage/ProjectList/ProjectList.tsx
@@ -0,0 +1,200 @@
+import { Button } from "@/components/ui/button";
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/components/ui/dialog";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { Skeleton } from "@/components/ui/skeleton";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+ // TableColumn,
+} from "@/components/ui/table";
+import { Textarea } from "@/components/ui/textarea";
+import { useToast } from "@/hooks/use-toast";
+import { PlusIcon, TrashIcon } from "lucide-react";
+import { useState } from "react";
+import { useCreateProject, useDeleteProject, useGetProjects } from "./queries";
+
+type Project = {
+ id: string;
+ name: string;
+ apiSpec: string;
+};
+
+export function ProjectList() {
+ const { data: projects, isLoading } = useGetProjects();
+ const [newProject, setNewProject] = useState({
+ id: "",
+ name: "",
+ apiSpec: "",
+ });
+ const { toast } = useToast();
+ const createProjectMutation = useCreateProject();
+ const deleteProjectMutation = useDeleteProject();
+
+ if (isLoading) {
+ return ;
+ }
+
+ const createProject = () => {
+ if (!newProject.name || !newProject.apiSpec) {
+ toast({
+ title: "Error",
+ description:
+ "Please enter a name and API specification for the project",
+ variant: "destructive",
+ });
+ return;
+ }
+
+ createProjectMutation.mutate(
+ {
+ name: newProject.name,
+ spec: newProject.apiSpec,
+ },
+ {
+ onSuccess: () => {
+ setNewProject({
+ id: "",
+ name: "",
+ apiSpec: "",
+ });
+ },
+ },
+ );
+ };
+
+ const deleteProject = (id: string) => {
+ deleteProjectMutation.mutate(id);
+ };
+
+ return (
+
+
+
Projects
+
+
+
+
+
+
+ Name
+ API Spec
+ Actions
+
+
+
+ {projects?.map((project) => (
+
+ {project.name}
+ {project.spec?.substring(0, 50)}...
+
+
+
+
+ ))}
+
+
+
+ );
+}
+
+function ProjectListSkeleton() {
+ return (
+
+
Projects
+
+
+
+ Name
+ Description
+ Created At
+ Actions
+
+
+
+ {[...Array(3)].map((_, index) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/lilo/lilo-frontend/src/pages/DashboardPage/ProjectList/index.ts b/lilo/lilo-frontend/src/pages/DashboardPage/ProjectList/index.ts
new file mode 100644
index 000000000..0e9529f98
--- /dev/null
+++ b/lilo/lilo-frontend/src/pages/DashboardPage/ProjectList/index.ts
@@ -0,0 +1 @@
+export { ProjectList } from "./ProjectList";
diff --git a/lilo/lilo-frontend/src/pages/DashboardPage/ProjectList/queries.ts b/lilo/lilo-frontend/src/pages/DashboardPage/ProjectList/queries.ts
new file mode 100644
index 000000000..e8033a804
--- /dev/null
+++ b/lilo/lilo-frontend/src/pages/DashboardPage/ProjectList/queries.ts
@@ -0,0 +1,73 @@
+import { useToast } from "@/hooks/use-toast";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+import { hc } from "hono/client";
+import type { ProjectsRouter } from "../../../../../lilo-worker/src/routes/internal";
+
+const projectsClient = hc("/internal/projects");
+
+const QUERY_KEY = "user-projects";
+
+export function useGetProjects() {
+ return useQuery({
+ queryKey: [QUERY_KEY],
+ // TODO - Add error handling
+ queryFn: () => projectsClient.index.$get().then((res) => res.json()),
+ });
+}
+
+export function useDeleteProject() {
+ const { toast } = useToast();
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (id: string) =>
+ projectsClient[":id"].$delete({
+ param: { id },
+ }),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
+ toast({
+ title: "Project Deleted",
+ description: "The project has been deleted successfully.",
+ });
+ },
+ onError: () => {
+ toast({
+ title: "Error",
+ description: "Failed to delete project",
+ variant: "destructive",
+ });
+ },
+ });
+}
+
+type CreateProjectPayload = {
+ name: string;
+ spec: string;
+};
+
+export function useCreateProject() {
+ const { toast } = useToast();
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (payload: CreateProjectPayload) =>
+ projectsClient.index.$post({
+ json: payload,
+ }),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
+ toast({
+ title: "Project Created",
+ description: "Your new project has been created successfully.",
+ });
+ },
+ onError: () => {
+ toast({
+ title: "Error",
+ description: "Failed to create project",
+ variant: "destructive",
+ });
+ },
+ });
+}
diff --git a/lilo/lilo-frontend/src/pages/DashboardPage/index.tsx b/lilo/lilo-frontend/src/pages/DashboardPage/index.tsx
new file mode 100644
index 000000000..a66b98a00
--- /dev/null
+++ b/lilo/lilo-frontend/src/pages/DashboardPage/index.tsx
@@ -0,0 +1 @@
+export { DashboardPage } from "./DashboardPage";
diff --git a/lilo/lilo-frontend/src/vite-env.d.ts b/lilo/lilo-frontend/src/vite-env.d.ts
new file mode 100644
index 000000000..11f02fe2a
--- /dev/null
+++ b/lilo/lilo-frontend/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/lilo/lilo-frontend/tailwind.config.js b/lilo/lilo-frontend/tailwind.config.js
new file mode 100644
index 000000000..248760474
--- /dev/null
+++ b/lilo/lilo-frontend/tailwind.config.js
@@ -0,0 +1,57 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ darkMode: ["class"],
+ content: ["./index.html", "./src/**/*.{ts,tsx,js,jsx}"],
+ theme: {
+ extend: {
+ borderRadius: {
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ colors: {
+ background: "hsl(var(--background))",
+ foreground: "hsl(var(--foreground))",
+ card: {
+ DEFAULT: "hsl(var(--card))",
+ foreground: "hsl(var(--card-foreground))",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover))",
+ foreground: "hsl(var(--popover-foreground))",
+ },
+ primary: {
+ DEFAULT: "hsl(var(--primary))",
+ foreground: "hsl(var(--primary-foreground))",
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary))",
+ foreground: "hsl(var(--secondary-foreground))",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted))",
+ foreground: "hsl(var(--muted-foreground))",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent))",
+ foreground: "hsl(var(--accent-foreground))",
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive))",
+ foreground: "hsl(var(--destructive-foreground))",
+ },
+ border: "hsl(var(--border))",
+ input: "hsl(var(--input))",
+ ring: "hsl(var(--ring))",
+ chart: {
+ 1: "hsl(var(--chart-1))",
+ 2: "hsl(var(--chart-2))",
+ 3: "hsl(var(--chart-3))",
+ 4: "hsl(var(--chart-4))",
+ 5: "hsl(var(--chart-5))",
+ },
+ },
+ },
+ },
+ plugins: [require("tailwindcss-animate")],
+};
diff --git a/lilo/lilo-frontend/tsconfig.app.json b/lilo/lilo-frontend/tsconfig.app.json
new file mode 100644
index 000000000..8472b4edf
--- /dev/null
+++ b/lilo/lilo-frontend/tsconfig.app.json
@@ -0,0 +1,36 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ // HACK - This is a workaround to be able to import the Hono app types for Hono RPC client
+ "types": ["@types/node", "@cloudflare/workers-types"],
+
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true,
+
+ "baseUrl": ".",
+ "paths": {
+ "@/*": [
+ "./src/*"
+ ]
+ }
+ },
+ "include": ["src"]
+}
diff --git a/lilo/lilo-frontend/tsconfig.json b/lilo/lilo-frontend/tsconfig.json
new file mode 100644
index 000000000..856b92690
--- /dev/null
+++ b/lilo/lilo-frontend/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ],
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ }
+}
diff --git a/lilo/lilo-frontend/tsconfig.node.json b/lilo/lilo-frontend/tsconfig.node.json
new file mode 100644
index 000000000..db0becc8b
--- /dev/null
+++ b/lilo/lilo-frontend/tsconfig.node.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/lilo/lilo-frontend/vite.config.ts b/lilo/lilo-frontend/vite.config.ts
new file mode 100644
index 000000000..7bd07ee27
--- /dev/null
+++ b/lilo/lilo-frontend/vite.config.ts
@@ -0,0 +1,23 @@
+import path from "node:path";
+import react from "@vitejs/plugin-react";
+import { defineConfig } from "vite";
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ resolve: {
+ alias: {
+ "@": path.resolve(__dirname, "./src"),
+ },
+ },
+ server: {
+ port: 3005,
+ proxy: {
+ "/api": "http://localhost:6246",
+ "/internal": "http://localhost:6246",
+ "/auth": "http://localhost:6246",
+ "/reference": "http://localhost:6246",
+ "/doc": "http://localhost:6246",
+ },
+ },
+});
diff --git a/lilo/lilo-worker/.dev.vars.example b/lilo/lilo-worker/.dev.vars.example
new file mode 100644
index 000000000..8bed11415
--- /dev/null
+++ b/lilo/lilo-worker/.dev.vars.example
@@ -0,0 +1,12 @@
+SESSION_SECRET=""
+PUBLIC_KEY=""
+PRIVATE_KEY=""
+GITHUB_ID=
+GITHUB_SECRET=
+
+# For local development with the SPA,
+# helps with redirecting
+LILO_ENV=local
+
+# For local development with Fiberplane studio
+FPX_ENDPOINT=http://localhost:8788/v1/traces
diff --git a/lilo/lilo-worker/.gitignore b/lilo/lilo-worker/.gitignore
new file mode 100644
index 000000000..5fe6c43e8
--- /dev/null
+++ b/lilo/lilo-worker/.gitignore
@@ -0,0 +1,36 @@
+# prod
+dist/
+public/
+# dev
+.yarn/
+!.yarn/releases
+.vscode/*
+!.vscode/launch.json
+!.vscode/*.code-snippets
+.idea/workspace.xml
+.idea/usage.statistics.xml
+.idea/shelf
+
+# deps
+node_modules/
+.wrangler
+
+# env
+.env
+.env.production
+.dev.vars
+.prod.vars
+
+# logs
+logs/
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+# misc
+.DS_Store
+
+.wrangler
\ No newline at end of file
diff --git a/lilo/lilo-worker/.prod.vars.example b/lilo/lilo-worker/.prod.vars.example
new file mode 100644
index 000000000..c5db0d115
--- /dev/null
+++ b/lilo/lilo-worker/.prod.vars.example
@@ -0,0 +1,3 @@
+CLOUDFLARE_D1_TOKEN=""
+CLOUDFLARE_ACCOUNT_ID=""
+CLOUDFLARE_DATABASE_ID=""
\ No newline at end of file
diff --git a/lilo/lilo-worker/README.md b/lilo/lilo-worker/README.md
new file mode 100644
index 000000000..2663ce45c
--- /dev/null
+++ b/lilo/lilo-worker/README.md
@@ -0,0 +1,106 @@
+## Lilo
+
+### Getting started
+
+Copy the `.dev.vars.example` file to `.dev.vars` and fill in the values:
+
+```sh
+cp .dev.vars.example .dev.vars
+```
+
+> NOTE: If you're using the local dev mode, you'll need to make sure `LILO_ENV=local` in your `.dev.vars` file, so that the session cookie's `sameSite` is set to `none` and the SPA can use it.
+
+You'll need GitHub OAuth app credentials for the dashboard. You can create your own or ask for Brett's.
+
+You'll want to initialize the D1 database for your project.
+
+```sh
+pnpm db:touch
+pnpm db:generate
+pnpm db:migrate
+```
+
+### (TODO) Project structure
+
+```#
+├── src
+│ ├── index.ts # Hono app entry point
+│ └── db
+│ └── schema.ts # Database schema
+├── .dev.vars.example # Example .dev.vars file
+├── .prod.vars.example # Example .prod.vars file
+├── seed.ts # Optional script to seed the db
+├── drizzle.config.ts # Drizzle configuration
+├── package.json
+├── tsconfig.json # TypeScript configuration
+└── wrangler.toml # Cloudflare Workers configuration
+```
+
+### Commands for local development
+
+Run the development server:
+
+```sh
+pnpm dev
+```
+
+As you iterate on the database schema, you'll need to generate a new migration file and apply it like so:
+
+```sh
+pnpm db:generate
+pnpm db:migrate
+```
+
+### Commands for deployment
+
+Lilo is already attached to a D1 database. You can find the database id in the `wrangler.toml` file.
+
+If you need to run migrations on the production database, you need to set the following information in a `.prod.vars` file:
+
+```sh
+CLOUDFLARE_D1_TOKEN=""
+CLOUDFLARE_ACCOUNT_ID=""
+CLOUDFLARE_DATABASE_ID=""
+```
+
+If you haven’t generated the latest migration files yet, run:
+```shell
+pnpm db:generate
+```
+
+Afterwards, run the migration script for production:
+```shell
+pnpm db:migrate:prod
+```
+
+
+Finally, deploy
+
+```shell
+pnpm run deploy
+```
+
+#### Setting secrets
+
+Set GitHub OAuth credentials
+
+```sh
+pnpx wrangler secret put GITHUB_ID
+pnpx wrangler secret put GITHUB_SECRET
+```
+
+Set secrets for external api auth
+
+```sh
+pnpm keypair:generate:prod
+# I prefer to upload the keys as secrets in the wrangler dashboard, since they have newlines
+```
+
+Create a session secret
+
+```sh
+pnpm session:generate
+```
+
+
+
diff --git a/lilo/lilo-worker/add-allowed-user.ts b/lilo/lilo-worker/add-allowed-user.ts
new file mode 100644
index 000000000..8a761409c
--- /dev/null
+++ b/lilo/lilo-worker/add-allowed-user.ts
@@ -0,0 +1,240 @@
+import fs from "node:fs";
+import path from "node:path";
+import { config } from "dotenv";
+import {
+ drizzle as drizzleLibsql,
+ type LibSQLDatabase,
+} from "drizzle-orm/libsql";
+// import type { SQLiteTable } from "drizzle-orm/sqlite-core";
+import {
+ type AsyncBatchRemoteCallback,
+ type AsyncRemoteCallback,
+ drizzle as drizzleSQLiteProxy,
+ type SqliteRemoteDatabase,
+} from "drizzle-orm/sqlite-proxy";
+import { createClient } from "@libsql/client";
+
+import * as schema from "./src/db/schema";
+
+// biome-ignore lint/suspicious/noExplicitAny: Centralize usage of `any` type (we use it in db results that are not worth typing)
+type Any = any;
+
+addAllowedUser();
+
+async function addAllowedUser() {
+ const db = process.env.ENVIRONMENT === "production"
+ ? await getProductionDatabase()
+ : await getLocalDatabase();
+
+ const args = process.argv.slice(2);
+ if (args.length === 0) {
+ console.error("No usernames provided");
+ process.exit(1);
+ }
+
+ console.log("Adding allowed users:", args.join(", "));
+
+ for (const githubUsername of args) {
+ await db.insert(schema.allowedUsers).values({
+ githubUsername,
+ });
+ }
+}
+
+/**
+ * Creates a connection to the local D1 SQLite database and returns a Drizzle ORM instance.
+ * @returns {Promise} Drizzle ORM instance connected to local database
+ * @throws {Error} If local database path cannot be resolved
+ */
+async function getLocalDatabase(): Promise<
+ LibSQLDatabase>
+> {
+ console.log("Using local SQLite database");
+ const dbPath = getLocalSQLiteDBPath();
+
+ if (!dbPath) {
+ console.error("Database seed failed: local DB could not be resolved");
+ process.exit(1);
+ }
+
+ const client = createClient({
+ url: `file:${dbPath}`,
+ });
+
+ return drizzleLibsql(client);
+}
+
+
+/**
+ * Creates a connection to the production Cloudflare D1 database and returns a Drizzle ORM instance.
+ * Loads production environment variables from .prod.vars file.
+ * @returns {Promise} Drizzle ORM instance connected to production database
+ * @throws {Error} If required environment variables are not set
+ */
+async function getProductionDatabase(): Promise<
+ SqliteRemoteDatabase>
+> {
+ console.warn("Using production D1 database");
+ config({ path: ".prod.vars" });
+
+ const apiToken = process.env.CLOUDFLARE_D1_TOKEN;
+ const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
+ const databaseId = process.env.CLOUDFLARE_DATABASE_ID;
+
+ if (!apiToken || !accountId || !databaseId) {
+ console.error(
+ "Database seed failed: production environment variables not set (make sure you have a .prod.vars file)",
+ );
+ process.exit(1);
+ }
+
+ return createProductionD1Connection(accountId, databaseId, apiToken);
+}
+
+/**
+ * Creates a connection to a remote Cloudflare D1 database using the sqlite-proxy driver.
+ * @param {string} accountId - Cloudflare account ID
+ * @param {string} databaseId - D1 database ID
+ * @param {string} apiToken - Cloudflare API token with write access to D1
+ * @returns {SqliteRemoteDatabase} Drizzle ORM instance connected to remote database
+ */
+export function createProductionD1Connection(
+ accountId: string,
+ databaseId: string,
+ apiToken: string,
+) {
+ /**
+ * Executes a single query against the Cloudflare D1 HTTP API.
+ *
+ * @param {string} accountId - Cloudflare account ID
+ * @param {string} databaseId - D1 database ID
+ * @param {string} apiToken - Cloudflare API token with write access to D1
+ * @param {string} sql - The SQL statement to execute
+ * @param {any[]} params - Parameters for the SQL statement
+ * @param {string} method - The method type for the SQL operation
+ * @returns {Promise<{ rows: any[][] }>} The result rows from the query
+ * @throws {Error} If the HTTP request fails or returns an error
+ */
+ async function executeCloudflareD1Query(
+ accountId: string,
+ databaseId: string,
+ apiToken: string,
+ sql: string,
+ params: Any[],
+ method: string,
+ ): Promise<{ rows: Any[][] }> {
+ const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/d1/database/${databaseId}/query`;
+
+ const res = await fetch(url, {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${apiToken}`,
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ sql, params, method }),
+ });
+
+ const data: Any = await res.json();
+
+ if (res.status !== 200) {
+ throw new Error(
+ `Error from sqlite proxy server: ${res.status} ${res.statusText}\n${JSON.stringify(data)}`,
+ );
+ }
+
+ if (data.errors.length > 0 || !data.success) {
+ throw new Error(
+ `Error from sqlite proxy server: \n${JSON.stringify(data)}}`,
+ );
+ }
+
+ const qResult = data?.result?.[0];
+
+ if (!qResult?.success) {
+ throw new Error(
+ `Error from sqlite proxy server: \n${JSON.stringify(data)}`,
+ );
+ }
+
+ return { rows: qResult.results.map((r: Any) => Object.values(r)) };
+ }
+
+ /**
+ * Asynchronously executes a single query.
+ */
+ const queryClient: AsyncRemoteCallback = async (sql, params, method) => {
+ return executeCloudflareD1Query(
+ accountId,
+ databaseId,
+ apiToken,
+ sql,
+ params,
+ method,
+ );
+ };
+
+ /**
+ * Asynchronously executes a batch of queries.
+ */
+ const batchQueryClient: AsyncBatchRemoteCallback = async (queries) => {
+ const results: { rows: Any[][] }[] = [];
+
+ for (const query of queries) {
+ const { sql, params, method } = query;
+ const result = await executeCloudflareD1Query(
+ accountId,
+ databaseId,
+ apiToken,
+ sql,
+ params,
+ method,
+ );
+ results.push(result);
+ }
+
+ return results;
+ };
+
+ return drizzleSQLiteProxy(queryClient, batchQueryClient);
+}
+
+/**
+ * Used when connecting to local SQLite db during seeding and migrations,
+ * or when making queries against the db.
+ * @returns Path to most recent .sqlite file in the .wrangler directory
+ */
+function getLocalSQLiteDBPath() {
+ try {
+ // .wrangler dir and process execution are assumed to be colocated
+ const basePath = path.resolve(".wrangler");
+
+ const files = fs
+ .readdirSync(basePath, {
+ encoding: "utf-8",
+ recursive: true,
+ })
+ .filter((fileName) => fileName.endsWith(".sqlite"));
+
+ if (!files.length) {
+ throw new Error(`No .sqlite file found at ${basePath}`);
+ }
+
+ // Retrieve most recent .sqlite file
+ files.sort((a, b) => {
+ const statA = fs.statSync(path.join(basePath, a));
+ const statB = fs.statSync(path.join(basePath, b));
+
+ return statB.mtime.getTime() - statA.mtime.getTime();
+ });
+
+ return path.resolve(basePath, files[0]);
+ } catch (error) {
+ if (error instanceof Error) {
+ throw new Error(`Error resolving local D1 DB: ${error.message}`, {
+ cause: error,
+ });
+ }
+
+ throw new Error("Error resolving local D1 DB", { cause: error });
+ }
+}
\ No newline at end of file
diff --git a/lilo/lilo-worker/biome.jsonc b/lilo/lilo-worker/biome.jsonc
new file mode 100644
index 000000000..d72d7fb75
--- /dev/null
+++ b/lilo/lilo-worker/biome.jsonc
@@ -0,0 +1,13 @@
+{
+ "$schema": "../../node_modules/@biomejs/biome/configuration_schema.json",
+ "extends": ["../../biome.jsonc"],
+ "files": {
+ "ignore": [
+ "public",
+ "node_modules",
+ ".wrangler",
+ "tsconfig.json",
+ "drizzle"
+ ]
+ }
+}
diff --git a/lilo/lilo-worker/drizzle.config.ts b/lilo/lilo-worker/drizzle.config.ts
new file mode 100644
index 000000000..cc2fae689
--- /dev/null
+++ b/lilo/lilo-worker/drizzle.config.ts
@@ -0,0 +1,70 @@
+import fs from "node:fs";
+import path from "node:path";
+import { config } from "dotenv";
+import { defineConfig } from "drizzle-kit";
+
+let dbConfig: ReturnType;
+if (process.env.ENVIRONMENT === "production") {
+ console.log("Using production database");
+ config({ path: "./.prod.vars" });
+ dbConfig = defineConfig({
+ schema: "./src/db/schema.ts",
+ out: "./drizzle/migrations",
+ dialect: "sqlite",
+ driver: "d1-http",
+ dbCredentials: {
+ accountId: process.env.CLOUDFLARE_ACCOUNT_ID ?? "",
+ databaseId: process.env.CLOUDFLARE_DATABASE_ID ?? "",
+ token: process.env.CLOUDFLARE_D1_TOKEN ?? "",
+ },
+ });
+} else {
+ console.log("Using local database");
+ config({ path: "./.dev.vars" });
+ const localD1DB = getLocalD1DB();
+ if (!localD1DB) {
+ process.exit(1);
+ }
+
+ dbConfig = defineConfig({
+ schema: "./src/db/schema.ts",
+ out: "./drizzle/migrations",
+ dialect: "sqlite",
+ dbCredentials: {
+ url: localD1DB,
+ },
+ });
+}
+
+export default dbConfig;
+
+function getLocalD1DB() {
+ try {
+ const basePath = path.resolve(".wrangler");
+ const files = fs
+ .readdirSync(basePath, { encoding: "utf-8", recursive: true })
+ .filter((f) => f.endsWith(".sqlite"));
+
+ // In case there are multiple .sqlite files, we want the most recent one.
+ files.sort((a, b) => {
+ const statA = fs.statSync(path.join(basePath, a));
+ const statB = fs.statSync(path.join(basePath, b));
+ return statB.mtime.getTime() - statA.mtime.getTime();
+ });
+ const dbFile = files[0];
+
+ if (!dbFile) {
+ throw new Error(`.sqlite file not found in ${basePath}`);
+ }
+
+ const url = path.resolve(basePath, dbFile);
+
+ return url;
+ } catch (err) {
+ if (err instanceof Error) {
+ console.log(`Error resolving local D1 DB: ${err.message}`);
+ } else {
+ console.log(`Error resolving local D1 DB: ${err}`);
+ }
+ }
+}
diff --git a/lilo/lilo-worker/drizzle/migrations/0000_lowly_the_twelve.sql b/lilo/lilo-worker/drizzle/migrations/0000_lowly_the_twelve.sql
new file mode 100644
index 000000000..6eaeaffb7
--- /dev/null
+++ b/lilo/lilo-worker/drizzle/migrations/0000_lowly_the_twelve.sql
@@ -0,0 +1,48 @@
+CREATE TABLE `api_keys` (
+ `id` text PRIMARY KEY NOT NULL,
+ `user_id` text NOT NULL,
+ `name` text,
+ `key` text NOT NULL,
+ `createdAt` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
+ `updated_at` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
+ FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action
+);
+--> statement-breakpoint
+CREATE TABLE `projects` (
+ `id` text PRIMARY KEY NOT NULL,
+ `name` text NOT NULL,
+ `spec` text,
+ `user_id` text NOT NULL,
+ `createdAt` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
+ `updated_at` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
+ FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action
+);
+--> statement-breakpoint
+CREATE TABLE `queries` (
+ `id` text PRIMARY KEY NOT NULL,
+ `api_key_id` text NOT NULL,
+ `query` text NOT NULL,
+ `createdAt` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
+ `updated_at` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
+ FOREIGN KEY (`api_key_id`) REFERENCES `api_keys`(`id`) ON UPDATE no action ON DELETE no action
+);
+--> statement-breakpoint
+CREATE TABLE `sessions` (
+ `id` text PRIMARY KEY NOT NULL,
+ `user_id` text NOT NULL,
+ `expires_at` text NOT NULL,
+ `createdAt` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
+ `updated_at` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
+ FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action
+);
+--> statement-breakpoint
+CREATE TABLE `users` (
+ `id` text PRIMARY KEY NOT NULL,
+ `email` text NOT NULL,
+ `github_username` text NOT NULL,
+ `avatar_url` text,
+ `createdAt` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
+ `updated_at` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL
+);
+--> statement-breakpoint
+CREATE UNIQUE INDEX `users_email_unique` ON `users` (`email`);
\ No newline at end of file
diff --git a/lilo/lilo-worker/drizzle/migrations/0001_special_makkari.sql b/lilo/lilo-worker/drizzle/migrations/0001_special_makkari.sql
new file mode 100644
index 000000000..2ec1c820a
--- /dev/null
+++ b/lilo/lilo-worker/drizzle/migrations/0001_special_makkari.sql
@@ -0,0 +1,19 @@
+CREATE TABLE `allowed_users` (
+ `github_username` text PRIMARY KEY NOT NULL,
+ `createdAt` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL,
+ `updated_at` text DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) NOT NULL
+);
+--> statement-breakpoint
+ALTER TABLE `users` ADD `allowed` integer DEFAULT false NOT NULL;
+--> statement-breakpoint
+INSERT INTO `allowed_users` (`github_username`) VALUES
+ ('brettimus'),
+ ('mies'),
+ ('flenter'),
+ ('keturiosakys'),
+ ('oscarvz'),
+ ('Nleal'),
+ ('mellowagain'),
+ ('stephlow'),
+ ('hatchan'),
+ ('simonjeal');
diff --git a/lilo/lilo-worker/drizzle/migrations/meta/0000_snapshot.json b/lilo/lilo-worker/drizzle/migrations/meta/0000_snapshot.json
new file mode 100644
index 000000000..9f1c76675
--- /dev/null
+++ b/lilo/lilo-worker/drizzle/migrations/meta/0000_snapshot.json
@@ -0,0 +1,338 @@
+{
+ "version": "6",
+ "dialect": "sqlite",
+ "id": "e8a9341a-a687-4f77-a6f7-2e87f130ce95",
+ "prevId": "00000000-0000-0000-0000-000000000000",
+ "tables": {
+ "api_keys": {
+ "name": "api_keys",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "key": {
+ "name": "key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "api_keys_user_id_users_id_fk": {
+ "name": "api_keys_user_id_users_id_fk",
+ "tableFrom": "api_keys",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "projects": {
+ "name": "projects",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "spec": {
+ "name": "spec",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "projects_user_id_users_id_fk": {
+ "name": "projects_user_id_users_id_fk",
+ "tableFrom": "projects",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "queries": {
+ "name": "queries",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "api_key_id": {
+ "name": "api_key_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "query": {
+ "name": "query",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "queries_api_key_id_api_keys_id_fk": {
+ "name": "queries_api_key_id_api_keys_id_fk",
+ "tableFrom": "queries",
+ "tableTo": "api_keys",
+ "columnsFrom": [
+ "api_key_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "sessions": {
+ "name": "sessions",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "sessions_user_id_users_id_fk": {
+ "name": "sessions_user_id_users_id_fk",
+ "tableFrom": "sessions",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "users": {
+ "name": "users",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "github_username": {
+ "name": "github_username",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "avatar_url": {
+ "name": "avatar_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ }
+ },
+ "indexes": {
+ "users_email_unique": {
+ "name": "users_email_unique",
+ "columns": [
+ "email"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ }
+ },
+ "views": {},
+ "enums": {},
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "indexes": {}
+ }
+}
\ No newline at end of file
diff --git a/lilo/lilo-worker/drizzle/migrations/meta/0001_snapshot.json b/lilo/lilo-worker/drizzle/migrations/meta/0001_snapshot.json
new file mode 100644
index 000000000..94fc05d1b
--- /dev/null
+++ b/lilo/lilo-worker/drizzle/migrations/meta/0001_snapshot.json
@@ -0,0 +1,379 @@
+{
+ "version": "6",
+ "dialect": "sqlite",
+ "id": "68130043-4c23-4cb8-9e46-747408d3084d",
+ "prevId": "e8a9341a-a687-4f77-a6f7-2e87f130ce95",
+ "tables": {
+ "allowed_users": {
+ "name": "allowed_users",
+ "columns": {
+ "github_username": {
+ "name": "github_username",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "api_keys": {
+ "name": "api_keys",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "key": {
+ "name": "key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "api_keys_user_id_users_id_fk": {
+ "name": "api_keys_user_id_users_id_fk",
+ "tableFrom": "api_keys",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "projects": {
+ "name": "projects",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "spec": {
+ "name": "spec",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "projects_user_id_users_id_fk": {
+ "name": "projects_user_id_users_id_fk",
+ "tableFrom": "projects",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "queries": {
+ "name": "queries",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "api_key_id": {
+ "name": "api_key_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "query": {
+ "name": "query",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "queries_api_key_id_api_keys_id_fk": {
+ "name": "queries_api_key_id_api_keys_id_fk",
+ "tableFrom": "queries",
+ "tableTo": "api_keys",
+ "columnsFrom": [
+ "api_key_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "sessions": {
+ "name": "sessions",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "sessions_user_id_users_id_fk": {
+ "name": "sessions_user_id_users_id_fk",
+ "tableFrom": "sessions",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "users": {
+ "name": "users",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "github_username": {
+ "name": "github_username",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "allowed": {
+ "name": "allowed",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ },
+ "avatar_url": {
+ "name": "avatar_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
+ }
+ },
+ "indexes": {
+ "users_email_unique": {
+ "name": "users_email_unique",
+ "columns": [
+ "email"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ }
+ },
+ "views": {},
+ "enums": {},
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "indexes": {}
+ }
+}
\ No newline at end of file
diff --git a/lilo/lilo-worker/drizzle/migrations/meta/_journal.json b/lilo/lilo-worker/drizzle/migrations/meta/_journal.json
new file mode 100644
index 000000000..0513d243b
--- /dev/null
+++ b/lilo/lilo-worker/drizzle/migrations/meta/_journal.json
@@ -0,0 +1,20 @@
+{
+ "version": "7",
+ "dialect": "sqlite",
+ "entries": [
+ {
+ "idx": 0,
+ "version": "6",
+ "when": 1734021209466,
+ "tag": "0000_lowly_the_twelve",
+ "breakpoints": true
+ },
+ {
+ "idx": 1,
+ "version": "6",
+ "when": 1734026698492,
+ "tag": "0001_special_makkari",
+ "breakpoints": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/lilo/lilo-worker/keypair-generate.ts b/lilo/lilo-worker/keypair-generate.ts
new file mode 100644
index 000000000..81a9837dc
--- /dev/null
+++ b/lilo/lilo-worker/keypair-generate.ts
@@ -0,0 +1,25 @@
+import { exportKey, generateKeyPair } from "./src/lib/crypto";
+
+const IS_LOCAL = process.env.ENVIRONMENT !== "production";
+
+function formatForLocal(key: string) {
+ return `"${key.trim().replace(/[\r\n]+/g, "\\n")}"`;
+}
+
+generateKeyPair().then(async (keys) => {
+ const publicKeyExport = await exportKey("public", keys.publicKey);
+ const formattedPublicKey = IS_LOCAL
+ ? formatForLocal(publicKeyExport)
+ : publicKeyExport;
+ console.log(`\n\n\npublic key export:\n\n${formattedPublicKey}\n`);
+
+ const privateKeyExport = await exportKey("private", keys.privateKey);
+ const formattedPrivateKey = IS_LOCAL
+ ? formatForLocal(privateKeyExport)
+ : privateKeyExport;
+ console.log(`\n\n\nprivate key export:\n\n${formattedPrivateKey}\n`);
+
+ console.log(
+ "\n\n!!! When adding to .dev.vars, use double quotes and write literal newlines !!!",
+ );
+});
diff --git a/lilo/lilo-worker/package.json b/lilo/lilo-worker/package.json
new file mode 100644
index 000000000..f3691ca89
--- /dev/null
+++ b/lilo/lilo-worker/package.json
@@ -0,0 +1,48 @@
+{
+ "name": "lilo-worker",
+ "description": "api to generate and serve openapi specs with an assistant",
+ "scripts": {
+ "dev": "wrangler dev src/index.tsx",
+ "deploy": "wrangler deploy --minify src/index.tsx",
+ "db:touch": "wrangler d1 execute lilo-d1-database --local --command='SELECT 1'",
+ "db:generate": "drizzle-kit generate",
+ "db:migrate": "wrangler d1 migrations apply lilo-d1-database --local",
+ "db:migrate:prod": "ENVIRONMENT=production drizzle-kit migrate",
+ "db:seed": "tsx seed.ts",
+ "db:setup": "npm run db:touch && npm run db:generate && npm run db:migrate && npm run db:seed",
+ "db:studio": "drizzle-kit studio",
+ "db:studio:prod": "ENVIRONMENT=production drizzle-kit studio",
+ "format": "biome check . --write",
+ "keypair:generate": "tsx keypair-generate.ts",
+ "keypair:generate:prod": "ENVIRONMENT=production tsx keypair-generate.ts",
+ "session:generate": "tsx session-secret-generate.ts",
+ "add-allowed-user": "tsx add-allowed-user.ts",
+ "add-allowed-user:prod": "ENVIRONMENT=production tsx add-allowed-user.ts"
+ },
+ "dependencies": {
+ "@ai-sdk/google": "^1.0.9",
+ "@ai-sdk/openai": "^1.0.8",
+ "@fiberplane/embedded": "^0.0.9",
+ "@hono/oauth-providers": "^0.6.2",
+ "@hono/zod-openapi": "^0.18.0",
+ "@hono/zod-validator": "^0.4.1",
+ "@scalar/hono-api-reference": "^0.5.163",
+ "ai": "^4.0.16",
+ "dotenv": "^16.4.5",
+ "drizzle-orm": "^0.36.4",
+ "hono": "^4.6.7",
+ "jose": "^5.9.6",
+ "zod": "^3.23.8"
+ },
+ "devDependencies": {
+ "@biomejs/biome": "^1.9.4",
+ "@cloudflare/workers-types": "^4.20241205.0",
+ "@fiberplane/hono-otel": "workspace:*",
+ "@libsql/client": "^0.14.0",
+ "drizzle-kit": "^0.28.1",
+ "drizzle-seed": "^0.1.2",
+ "tsx": "^4.19.2",
+ "typescript": "^5.5.4",
+ "wrangler": "^3.95.0"
+ }
+}
diff --git a/lilo/lilo-worker/seed.ts b/lilo/lilo-worker/seed.ts
new file mode 100644
index 000000000..a0a923ed3
--- /dev/null
+++ b/lilo/lilo-worker/seed.ts
@@ -0,0 +1,59 @@
+import fs from "node:fs";
+import path from "node:path";
+import { createClient } from "@libsql/client";
+import { drizzle } from "drizzle-orm/libsql";
+import { seed } from "drizzle-seed";
+import * as schema from "./src/db/schema";
+
+const seedDatabase = async () => {
+ const pathToDb = getLocalD1DB();
+ const client = createClient({
+ url: `file:${pathToDb}`,
+ });
+ const db = drizzle(client);
+
+ try {
+ // Seed the database with initial data for users, projects, openAPISpecs, queries, and apiKeys
+ await seed(db, schema);
+ console.log("✅ Database seeded successfully!");
+ console.log("🪿 Run `npm run fiberplane` to explore data with your api.");
+ } catch (error) {
+ console.error("❌ Error seeding database:", error);
+ process.exit(1);
+ } finally {
+ process.exit(0);
+ }
+};
+
+function getLocalD1DB() {
+ try {
+ const basePath = path.resolve(".wrangler");
+ const files = fs
+ .readdirSync(basePath, { encoding: "utf-8", recursive: true })
+ .filter((f) => f.endsWith(".sqlite"));
+
+ // In case there are multiple .sqlite files, we want the most recent one.
+ files.sort((a, b) => {
+ const statA = fs.statSync(path.join(basePath, a));
+ const statB = fs.statSync(path.join(basePath, b));
+ return statB.mtime.getTime() - statA.mtime.getTime();
+ });
+ const dbFile = files[0];
+
+ if (!dbFile) {
+ throw new Error(`.sqlite file not found in ${basePath}`);
+ }
+
+ const url = path.resolve(basePath, dbFile);
+
+ return url;
+ } catch (err) {
+ if (err instanceof Error) {
+ console.log(`Error resolving local D1 DB: ${err.message}`);
+ } else {
+ console.log(`Error resolving local D1 DB: ${err}`);
+ }
+ }
+}
+
+seedDatabase();
diff --git a/lilo/lilo-worker/session-secret-generate.ts b/lilo/lilo-worker/session-secret-generate.ts
new file mode 100644
index 000000000..7d41abbe7
--- /dev/null
+++ b/lilo/lilo-worker/session-secret-generate.ts
@@ -0,0 +1,6 @@
+import { randomBytes } from "node:crypto";
+
+const generateSessionSecret = () => randomBytes(64).toString("hex");
+
+const sessionSecret = generateSessionSecret();
+console.log(`Your session secret:\n\n${sessionSecret}\n`);
diff --git a/lilo/lilo-worker/src/db/schema.ts b/lilo/lilo-worker/src/db/schema.ts
new file mode 100644
index 000000000..1aed6d24a
--- /dev/null
+++ b/lilo/lilo-worker/src/db/schema.ts
@@ -0,0 +1,103 @@
+import { randomUUID } from "node:crypto";
+import { sql } from "drizzle-orm";
+import { relations } from "drizzle-orm";
+import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
+
+const timestamps = {
+ createdAt: text()
+ .notNull()
+ .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`),
+ updatedAt: text("updated_at")
+ .notNull()
+ .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`),
+};
+
+export const users = sqliteTable("users", {
+ id: text("id")
+ .primaryKey()
+ .$defaultFn(() => randomUUID()),
+ email: text("email").notNull().unique(),
+ githubUsername: text("github_username").notNull(),
+ allowed: integer("allowed", { mode: "boolean" }).notNull().default(false),
+ avatarUrl: text("avatar_url"),
+ ...timestamps,
+});
+
+export const allowedUsers = sqliteTable("allowed_users", {
+ githubUsername: text("github_username").primaryKey(),
+ ...timestamps,
+});
+
+export type User = typeof users.$inferSelect;
+
+// For session based auth
+export const sessions = sqliteTable("sessions", {
+ id: text("id").primaryKey(),
+ userId: text("user_id")
+ .notNull()
+ .references(() => users.id),
+ expiresAt: text("expires_at").notNull(),
+ ...timestamps,
+});
+
+export const projects = sqliteTable("projects", {
+ id: text("id")
+ .primaryKey()
+ .$defaultFn(() => randomUUID()),
+ name: text("name").notNull(),
+ spec: text("spec"),
+ userId: text("user_id")
+ .notNull()
+ .references(() => users.id),
+ ...timestamps,
+});
+
+export const queries = sqliteTable("queries", {
+ id: text("id")
+ .primaryKey()
+ .$defaultFn(() => randomUUID()),
+ apiKeyId: text("api_key_id")
+ .notNull()
+ .references(() => apiKeys.id),
+ query: text("query").notNull(),
+ ...timestamps,
+});
+
+export const apiKeys = sqliteTable("api_keys", {
+ id: text("id")
+ .primaryKey()
+ .$defaultFn(() => randomUUID()),
+ userId: text("user_id")
+ .notNull()
+ .references(() => users.id),
+ name: text("name"),
+ key: text("key").notNull(),
+ ...timestamps,
+});
+
+export const usersRelations = relations(users, ({ many }) => ({
+ projects: many(projects),
+ apiKeys: many(apiKeys),
+}));
+
+export const projectsRelations = relations(projects, ({ one }) => ({
+ user: one(users, {
+ fields: [projects.userId],
+ references: [users.id],
+ }),
+}));
+
+export const queriesRelations = relations(queries, ({ one }) => ({
+ apiKey: one(apiKeys, {
+ fields: [queries.apiKeyId],
+ references: [apiKeys.id],
+ }),
+}));
+
+export const apiKeysRelations = relations(apiKeys, ({ one, many }) => ({
+ user: one(users, {
+ fields: [apiKeys.userId],
+ references: [users.id],
+ }),
+ queries: many(queries),
+}));
diff --git a/lilo/lilo-worker/src/index.tsx b/lilo/lilo-worker/src/index.tsx
new file mode 100644
index 000000000..3d10c4300
--- /dev/null
+++ b/lilo/lilo-worker/src/index.tsx
@@ -0,0 +1,73 @@
+import { instrument } from "@fiberplane/hono-otel";
+import { OpenAPIHono } from "@hono/zod-openapi";
+import { logger } from "hono/logger";
+import { dbMiddleware } from "./lib/db";
+import { externalApiRouter } from "./routes/external";
+import { internalApiRouter } from "./routes/internal/api";
+import { dashboardAuthRouter } from "./routes/internal/auth";
+import { apiReferenceRouter } from "./routes/reference";
+import type { AppType } from "./types";
+import { createMiddleware } from "@fiberplane/embedded";
+
+const app = new OpenAPIHono();
+
+// Add basic request logging
+app.use(logger());
+
+// Set drizzle database on context
+app.use(dbMiddleware);
+
+// Session authentication for the dashboard and internal api(NOT for the external api)
+app.route("/auth", dashboardAuthRouter);
+
+// Internal api
+app.route("/internal", internalApiRouter);
+
+// External api
+app.route("/api", externalApiRouter);
+
+// Mount OpenAPI documentation and Scalar API Reference
+app.doc("/doc", (c) => ({
+ openapi: "3.0.0",
+ info: {
+ title: "Lilo API",
+ version: "0.0.1",
+ description: "API documentation for Lilo",
+ },
+ servers: [
+ {
+ url: new URL(c.req.url).origin,
+ description: "Current environment",
+ },
+ ],
+}));
+
+// Mount the Fiberplane playground to play with the API
+app.use("/fp/*", createMiddleware({
+ cdn: "https://cdn.jsdelivr.net/npm/@fiberplane/embedded/dist/playground/",
+ // @ts-expect-error - The imported spec does not match our expected OpenAPIv3 type
+ spec: app.getOpenAPIDocument({
+ openapi: "3.0.0",
+ info: {
+ title: "Lilo API",
+ version: "0.0.1",
+ description: "API documentation for Lilo",
+ },
+ servers: [
+ {
+ // url: new URL(c.req.url).origin,
+ url: "http://localhost:6246",
+ description: "Local",
+ },
+ {
+ // url: new URL(c.req.url).origin,
+ url: "https://lilo.fp.dev",
+ description: "Production",
+ },
+ ],
+ }),
+}));
+
+app.route("/reference", apiReferenceRouter);
+
+export default instrument(app);
diff --git a/lilo/lilo-worker/src/lib/ai/index.ts b/lilo/lilo-worker/src/lib/ai/index.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/lilo/lilo-worker/src/lib/ai/inference.ts b/lilo/lilo-worker/src/lib/ai/inference.ts
new file mode 100644
index 000000000..bfd659b13
--- /dev/null
+++ b/lilo/lilo-worker/src/lib/ai/inference.ts
@@ -0,0 +1,289 @@
+import { google } from "@ai-sdk/google";
+import { generateObject } from "ai";
+import { z } from "zod";
+import {
+ PLANNER_SYSTEM_PROMPT,
+ STEP_REQUEST_EVALUATION_SYSTEM_PROMPT,
+ STEP_RESPONSE_EVALUATION_SYSTEM_PROMPT,
+ createPlanUserPrompt,
+} from "./prompts";
+
+// NOTE - Gemini does not play nicely with unions
+// So I removed `nullable` from the request schema
+const geminiRequestSchema = z.object({
+ path: z.string(),
+ pathParams: z.array(
+ z.object({
+ key: z.string(),
+ value: z.string(),
+ }),
+ ),
+ queryParams: z.array(
+ z.object({
+ key: z.string(),
+ value: z.string(),
+ }),
+ ),
+ body: z.string().nullable(),
+ bodyType: z.object({
+ type: z.enum(["json", "text", "form-data", "file"]),
+ isMultipart: z.boolean(),
+ }),
+ headers: z.array(
+ z.object({
+ key: z.string(),
+ value: z.string(),
+ }),
+ ),
+});
+
+const PlanStepSchema = z.object({
+ reasoning: z
+ .string()
+ .describe(
+ "the reason for calling this endpoint at this point in the sequence",
+ ),
+ routeId: z.number(),
+ route: z.object({
+ id: z.number(),
+ path: z.string(),
+ method: z.string(),
+ }),
+ exampleRequest: geminiRequestSchema.describe(
+ "Example request for the route handler",
+ ),
+ expectedOutput: z
+ .string()
+ .describe("a summary of the expected output for this api call"),
+ dependencies: z
+ .array(z.string())
+ .describe(
+ "The fully qualified dotpath of the dependencies on other steps in the execution plan",
+ ),
+});
+
+type PlanStep = z.infer;
+
+// NOTE - We cannot use `.optional` or `.nullable` from zod because it does not play nicely with structured output from openai... or gemini
+const GeminiPlanOutputSchema = z.object({
+ stepByStepReasoning: z.string(),
+ executionPlanSteps: z.array(PlanStepSchema),
+});
+
+/**
+ * Schema for the create plan request
+ *
+ * When you send this along, you will want
+ */
+const CreatePlanSchema = z.object({
+ prompt: z.string().describe("The prompt to use for the plan creation"),
+ messages: z
+ .array(
+ z.object({
+ role: z.enum(["user", "assistant"]),
+ content: z.string(),
+ }),
+ )
+ .optional()
+ .describe(
+ "The history of messages between the user and the AI, in ascending order (oldest messages first)",
+ ),
+});
+
+const NextStepSchema = z.object({
+ plan: z.object({
+ description: z.string(),
+ steps: z.array(PlanStepSchema),
+ }),
+ currentStepIdx: z.number(),
+ messages: z
+ .array(
+ z.object({
+ role: z.enum(["user", "assistant"]),
+ content: z.string(),
+ }),
+ )
+ .optional(),
+ previousResults: z.array(z.any()).nullable(),
+});
+
+const EvaluateNextStepAiResponseSchema = z.object({
+ action: z.enum(["execute", "awaitInput"]),
+ message: z.string().describe("A message to the user about the next step"),
+ modifiedStep: PlanStepSchema,
+});
+
+const EvaluateStepResponseAiResponseSchema = z.object({
+ action: z.enum(["continue", "awaitInput"]),
+ message: z.string().describe("A message to the user about the next step"),
+});
+
+const createStepResponseEvaluationUserPrompt = (
+ step: PlanStep,
+ // biome-ignore lint/suspicious/noExplicitAny:
+ stepResponse: any,
+) => {
+ return `
+You are an evaluator for a testing workflow.
+
+I need you to confirm that my most recent response for a step is expected, given our testing plan.
+
+If so, respond with "continue".
+If not, respond with "awaitInput".
+
+# Step
+${JSON.stringify(step, null, 2)}
+
+# Response
+${JSON.stringify(stepResponse, null, 2)}
+
+# Further instructions for you
+Provide CONCISE reasoning for why in plaintext. no markdown.
+`.trim();
+};
+
+const createStepEvaluationUserPrompt = (
+ currentStep: z.infer,
+ previousResults: z.infer["previousResults"],
+) => {
+ return `
+I need you to modify this to fit the existing testing plan.
+Sub in variables as necessary and correct any incorrect headers or things that need like auth tokens or whatever.
+
+# Existing Plan
+${JSON.stringify(currentStep, null, 2)}
+
+# Previous Results
+${JSON.stringify(previousResults, null, 2)}
+
+===
+
+Always response in valid json according to the schema i provided.
+`;
+};
+
+export async function evaluateNextStep({
+ plan,
+ currentStepIdx,
+ messages: history,
+ previousResults,
+}: z.infer) {
+ const currentStep = plan.steps[currentStepIdx];
+
+ const model = google("gemini-1.5-pro-latest");
+
+ const messages = [
+ ...(history ?? []),
+ { role: "assistant" as const, content: JSON.stringify(plan) },
+ {
+ role: "user" as const,
+ content: createStepEvaluationUserPrompt(currentStep, previousResults),
+ },
+ ];
+
+ const aiResponse = await generateObject({
+ model,
+ schema: EvaluateNextStepAiResponseSchema,
+ system: STEP_REQUEST_EVALUATION_SYSTEM_PROMPT,
+ temperature: 0.1,
+ messages,
+ });
+
+ return {
+ action: aiResponse.object.action,
+ message: aiResponse.object.message,
+ modifiedStep: transformPlanStep(aiResponse.object.modifiedStep),
+ };
+}
+
+export async function evaluateStepResponse({
+ plan,
+ currentStepIdx,
+ response: stepResponse,
+}: {
+ plan: z.infer["plan"];
+ currentStepIdx: number;
+ response: z.infer;
+}) {
+ const currentStep = plan.steps[currentStepIdx];
+
+ const model = google("gemini-1.5-pro-latest");
+
+ const messages = [
+ { role: "assistant" as const, content: JSON.stringify(plan) },
+ {
+ role: "user" as const,
+ content: createStepResponseEvaluationUserPrompt(
+ currentStep,
+ stepResponse,
+ ),
+ },
+ ];
+
+ const aiResponse = await generateObject({
+ model,
+ schema: EvaluateStepResponseAiResponseSchema,
+ system: STEP_RESPONSE_EVALUATION_SYSTEM_PROMPT,
+ temperature: 0.4,
+ messages,
+ });
+
+ return {
+ action: aiResponse.object.action,
+ message: aiResponse.object.message,
+ };
+}
+
+/**
+ * @TODO - Bring in the api spec!!!
+ */
+export async function createPlan(o: z.infer) {
+ const { prompt: userStory, messages: history } = o;
+ const model = google("gemini-1.5-pro-latest");
+ const expandedRouteHandlers: string[] = [];
+
+ const userPrompt = createPlanUserPrompt(
+ userStory,
+ expandedRouteHandlers
+ // .map(
+ // (r) => `Route ${r.routeId}: ${r.method} ${r.path}\n\n${r.context}`,
+ // )
+ .join("\n\n"),
+ );
+
+ const messages = [
+ ...(history ?? []),
+ {
+ role: "user" as const,
+ content: userPrompt,
+ },
+ ];
+ console.time("Create Plan Gemini call");
+ const result = await generateObject({
+ model: model,
+ schema: GeminiPlanOutputSchema,
+ system: PLANNER_SYSTEM_PROMPT,
+ temperature: 0.1,
+ messages,
+ });
+ console.timeEnd("Create Plan Gemini call");
+ const { object } = result;
+ const plan = object.executionPlanSteps.map(transformPlanStep);
+ return {
+ description: object.stepByStepReasoning,
+ plan,
+ };
+}
+
+function transformPlanStep(step: PlanStep) {
+ return {
+ routeId: step.route.id,
+ route: step.route,
+ reasoning: step.reasoning,
+ expectedOutput: step.expectedOutput,
+ dependencies: step.dependencies,
+
+ // NOTE: This is the shape of the data expected by the zustand store
+ payload: step.exampleRequest,
+ };
+}
diff --git a/lilo/lilo-worker/src/lib/ai/prompts.ts b/lilo/lilo-worker/src/lib/ai/prompts.ts
new file mode 100644
index 000000000..b2a76bf96
--- /dev/null
+++ b/lilo/lilo-worker/src/lib/ai/prompts.ts
@@ -0,0 +1,128 @@
+export const STEP_RESPONSE_EVALUATION_SYSTEM_PROMPT = cleanPrompt(`
+Your are an intelligent response evaluator whose purpose it is to understand whether to proceed with a sequence of steps.
+You're provided with the following:
+1. A user's goal, which you are to execute against.
+2. A list of steps to accomplish.
+3. A list of API endpoints to execute the steps against.
+4. The current step in the plan.
+5. The response from the current step.
+You need to determine whether the human should continue executing the next step, or whether they need to modify the current step some way,
+possibly by fixing their api or whatever.
+`);
+
+export const STEP_REQUEST_EVALUATION_SYSTEM_PROMPT = cleanPrompt(`
+Your are an intelligent task evaluator whose purpose it is to understand the next step to accomplish in a sequence of steps.
+You're provided with the following:
+1. A user's goal, which you are to execute against.
+2. A list of steps to accomplish.
+3. A list of API endpoints to execute the steps against.
+4. The current step in the plan.
+5. A history of previous steps.
+You need to fill in any necessary request details based on the history of previous steps and known dependencies for the current route,
+and you need to determine whether to pause for human input (e.g., to add an auth token or resource identifier),
+or whether to continue executing the next step.
+IMPORTANT - Sometimes you will need to substitute in IDs from previous requests into the plan, in order to make the testing flow end-to-end.
+If you do this, you must also update the plan's reasoning expectations for the result accordingly.
+For example: "" can be a placeholder for a resource id that we will learn in a previous step.
+Think it through. Take a deep breath.
+`);
+
+export const FLOW_EXECUTION_SYSTEM_PROMPT = cleanPrompt(`
+Your are an intelligent task executor whose purpose it is to execute all tasks as provided to you in sequence by calling
+the appropriate tools while outputting the requested information.
+You're provided with the following:
+1. A user's goal, which you are to execute against.
+2. A list of tasks to accomplish.
+3. A list of API endpoints to execute the tasks against. Map them against the respective tasks by name.
+You may skip tasks as necessary.
+Execute all tasks in order. Only respond once you've either run into an error you can't resolve or are finished.
+`);
+
+export const PLANNER_SYSTEM_PROMPT = `You are an end-to-end api tester.
+
+You translate user stories describing a testing flow of a json API into the correct routes to hit for that api.
+
+The user will describe some functionality they want to test for their api. You will receive a list of routes.
+
+Determine the order in which these routes should be executed.
+
+Populate request data for each route in your plan, according to the request schema.
+
+You will be provided the source code of a route handler for an API route, and you should generate
+query parameters, a request body, and headers that will test the request.
+
+Be clever and creative with test data. Avoid just writing things like "test".
+
+For example, if you get a route like \`/users/:id\`, you should return a URL like
+\`/users/10\` and a pathParams parameter like this:
+
+{ "path": "/users/10", "pathParams": { "key": ":id", "value": "10" } }
+
+*Remember to keep the colon in the pathParam key!*
+
+If you get a route like \`POST /users/:id\` with a handler like:
+
+\`\`\`ts
+async (c) => {
+ const token = c.req.headers.get("authorization")?.split(" ")[1]
+
+ const auth = c.get("authService");
+ const isAuthorized = await auth.isAuthorized(token)
+ if (!isAuthorized) {
+ return c.json({ message: "Unauthorized" }, 401)
+ }
+
+ const db = c.get("db");
+
+ const id = c.req.param('id');
+ const { email } = await c.req.json()
+
+ const user = (await db.update(user).set({ email }).where(eq(user.id, +id)).returning())?.[0];
+
+ if (!user) {
+ return c.json({ message: 'User not found' }, 404);
+ }
+
+ return c.json(user);
+}
+\`\`\`
+
+You should return a URL like:
+
+\`/users/64\` and a pathParams like:
+
+{ "path": "/users/64", "pathParams": { "key": ":id", "value": "64" } }
+
+and a header like:
+
+{ "headers": { "key": "authorization", "value": "Bearer " } }
+
+and a body like:
+
+{ email: "paul@beatles.music" }
+
+with a body type of "json"
+
+# Important
+
+If a route requires auth, record that as a dependency in some form. We will likely need user input while executing to to complete an auth flow.
+
+Feel free to use template-style strings in request fields, as we can substitute them in later.
+For example, "" can be a placeholder for a resource id that we will learn in a previous step.
+
+`.trim();
+
+export const createPlanUserPrompt = (userStory: string, routes: string) =>
+ `
+User story: ${userStory}
+
+Routes: ${routes}
+`.trim();
+
+export function cleanPrompt(prompt: string) {
+ return prompt
+ .trim()
+ .split("\n")
+ .map((l) => l.trim())
+ .join("\n");
+}
diff --git a/lilo/lilo-worker/src/lib/api-authenticate.ts b/lilo/lilo-worker/src/lib/api-authenticate.ts
new file mode 100644
index 000000000..4dcf18038
--- /dev/null
+++ b/lilo/lilo-worker/src/lib/api-authenticate.ts
@@ -0,0 +1,61 @@
+import type { Context, Next } from "hono";
+import * as jose from "jose";
+
+import type { AppType } from "../types";
+import { importKey } from "./crypto";
+import { getUserById } from "./db";
+
+/**
+ * A piece of middleware that handles JWT parsing and user lookup based off of the `sub` of the JWT.
+ *
+ * Sets variables on the Hono context for the bearerToken and currentUser.
+ */
+export const apiAuthenticate = async (c: Context, next: Next) => {
+ const authHeader = c.req.header("Authorization");
+
+ if (!authHeader || !authHeader.startsWith("Bearer ")) {
+ return c.json({ error: "Invalid or missing Authorization header" }, 401);
+ }
+
+ const bearerToken = authHeader.split(" ")?.[1]?.trim();
+
+ if (!bearerToken) {
+ return c.json({ message: "Unauthorized" }, 401);
+ }
+
+ // c.set("bearerToken", bearerToken);
+
+ const publicKey = await importKey("public", c.env.PUBLIC_KEY);
+
+ try {
+ const verifiedToken = await jose.jwtVerify(bearerToken, publicKey);
+ // c.set("verifiedToken", verifiedToken.payload);
+ const userId = verifiedToken?.payload?.sub ?? "";
+ if (!userId) {
+ return c.json({ message: "Unauthorized" }, 401);
+ }
+
+ const db = c.get("db");
+ const user = await getUserById(db, userId);
+
+ if (!user) {
+ return c.json({ message: "User not found" }, 404);
+ }
+
+ c.set("currentUser", user);
+
+ await next();
+ } catch (error) {
+ if (error instanceof jose.errors.JWTExpired) {
+ return c.json(
+ { errorType: "TOKEN_EXPIRED", message: "Token expired" },
+ 401,
+ );
+ }
+ // Handle other JWT verification errors
+ return c.json(
+ { errorType: "INVALID_TOKEN", message: "Invalid token" },
+ 401,
+ );
+ }
+};
diff --git a/lilo/lilo-worker/src/lib/crypto.ts b/lilo/lilo-worker/src/lib/crypto.ts
new file mode 100644
index 000000000..86b883b7d
--- /dev/null
+++ b/lilo/lilo-worker/src/lib/crypto.ts
@@ -0,0 +1,60 @@
+import * as jose from "jose";
+
+/**
+ * Generates an RSA key pair for signing and verifying.
+ */
+export function generateKeyPair() {
+ return crypto.subtle.generateKey(
+ {
+ name: "RSA-PSS",
+ modulusLength: 2048,
+ publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+ hash: "SHA-256",
+ },
+ true,
+ ["sign", "verify"],
+ ) as Promise;
+}
+
+/**
+ * Imports a public or private key from a PEM-formatted string.
+ */
+export function importKey(
+ keyType: "public" | "private",
+ key: string,
+): Promise {
+ const format = keyType === "public" ? "spki" : "pkcs8";
+ const keyUsage = keyType === "public" ? ["verify"] : ["sign"];
+
+ const replace =
+ /-----BEGIN (PUBLIC|PRIVATE) KEY-----|-----END (PUBLIC|PRIVATE) KEY-----|\n/g;
+
+ const keyData = new Uint8Array(
+ atob(key.replace(replace, ""))
+ .split("")
+ .map((c) => c.charCodeAt(0)),
+ );
+
+ return crypto.subtle.importKey(
+ format,
+ keyData,
+ {
+ name: "RSA-PSS",
+ hash: "SHA-256",
+ },
+ keyType === "public",
+ // @ts-ignore: TODO - fix this for frontend builds
+ keyUsage,
+ );
+}
+
+export async function exportKey(
+ keyType: "public" | "private",
+ key: CryptoKey,
+): Promise {
+ if (keyType === "public") {
+ return await jose.exportSPKI(key);
+ }
+
+ return await jose.exportPKCS8(key);
+}
diff --git a/lilo/lilo-worker/src/lib/db.ts b/lilo/lilo-worker/src/lib/db.ts
new file mode 100644
index 000000000..a7deee668
--- /dev/null
+++ b/lilo/lilo-worker/src/lib/db.ts
@@ -0,0 +1,30 @@
+import { eq } from "drizzle-orm";
+import { drizzle } from "drizzle-orm/d1";
+import type { Next } from "hono";
+
+import * as schema from "../db/schema";
+import type { User } from "../db/schema";
+import type { AppContext, DatabaseType } from "../types";
+
+/**
+ * Middleware to add the database to the context
+ */
+export const dbMiddleware = async (c: AppContext, next: Next) => {
+ const db = drizzle(c.env.DB);
+ c.set("db", db);
+ await next();
+};
+
+/**
+ * Get a user by their ID
+ */
+export const getUserById = async (
+ db: DatabaseType,
+ id: string,
+): Promise => {
+ const [user] = await db
+ .select()
+ .from(schema.users)
+ .where(eq(schema.users.id, id));
+ return user ?? null;
+};
diff --git a/lilo/lilo-worker/src/lib/jwt.ts b/lilo/lilo-worker/src/lib/jwt.ts
new file mode 100644
index 000000000..f89e47639
--- /dev/null
+++ b/lilo/lilo-worker/src/lib/jwt.ts
@@ -0,0 +1,64 @@
+import { z } from "zod";
+
+// Define the Zod schema for JWT payload
+const LiloJWTPayloadSchema = z.object({
+ sub: z.string(),
+ iat: z.number(),
+ nbf: z.number(),
+
+ // Additional standard JWT claims we don't support
+ exp: z.number().optional(),
+ iss: z.string().optional(),
+ aud: z.string().optional(),
+
+ // Custom claims
+ lilo_project_id: z.string().optional(),
+});
+
+export const createJwtPayload = (
+ userId: string,
+ projectId?: string,
+): JwtPayload => {
+ return {
+ sub: userId,
+ iat: Math.floor(Date.now() / 1000),
+ nbf: Math.floor(Date.now() / 1000),
+
+ // === Custom claims === //
+ // NOTE - projectId is optional because we haven't built support for project scoped keys yet
+ lilo_project_id: projectId,
+ };
+};
+
+// Infer the TypeScript type from the Zod schema
+export type JwtPayload = z.infer;
+
+// Type guard function using Zod schema
+export const isJwtPayload = (payload: unknown): payload is JwtPayload => {
+ const result = LiloJWTPayloadSchema.safeParse(payload);
+ return result.success;
+};
+
+// Example usage of the type guard
+export const validateJwtPayload = (payload: unknown): boolean => {
+ if (!isJwtPayload(payload)) {
+ return false;
+ }
+
+ const currentTimestamp = Math.floor(Date.now() / 1000);
+
+ // Validate timestamp claims
+ if (payload.iat > currentTimestamp) {
+ return false;
+ }
+
+ if (payload.nbf > currentTimestamp) {
+ return false;
+ }
+
+ if (payload.exp && payload.exp < currentTimestamp) {
+ return false;
+ }
+
+ return true;
+};
diff --git a/lilo/lilo-worker/src/lib/session-auth.ts b/lilo/lilo-worker/src/lib/session-auth.ts
new file mode 100644
index 000000000..c97f9b5c3
--- /dev/null
+++ b/lilo/lilo-worker/src/lib/session-auth.ts
@@ -0,0 +1,155 @@
+import { randomUUID } from "node:crypto";
+import { eq } from "drizzle-orm";
+import type { Next } from "hono";
+import { deleteCookie, getSignedCookie, setSignedCookie } from "hono/cookie";
+import { HTTPException } from "hono/http-exception";
+import * as schema from "../db/schema";
+import type { User } from "../db/schema";
+import type { AppContext, DatabaseType } from "../types";
+
+// Cookie config
+const EXPIRATION_TIME_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
+const COOKIE_MAX_AGE = Math.floor(EXPIRATION_TIME_MS / 1000);
+
+export const SESSION_COOKIE_NAME = "sid";
+
+export const requireSessionSecret = (c: AppContext, next: Next) => {
+ const sessionSecret = c.env.SESSION_SECRET;
+ if (!sessionSecret) {
+ throw new HTTPException(500, {
+ message: "Internal server error (CODE: OMG_001)",
+ });
+ }
+ return next();
+};
+
+/**
+ * Create a session for a user
+ * - Adds session to database
+ * - Sets signed session cookie
+ */
+export const createSession = async (
+ c: AppContext,
+ db: DatabaseType,
+ userId: string,
+) => {
+ const sessionToken = randomUUID();
+ await db.insert(schema.sessions).values({
+ userId,
+ id: sessionToken,
+ expiresAt: new Date(Date.now() + EXPIRATION_TIME_MS).toISOString(),
+ });
+
+ // NOTE: We use "none" in local mode to support cross-origin auth with the spa
+ const sameSite = c.env.LILO_ENV === "local" ? "none" : "Strict";
+
+ // Set session cookie with the session token
+ setSignedCookie(c, SESSION_COOKIE_NAME, sessionToken, c.env.SESSION_SECRET, {
+ httpOnly: true,
+ secure: true,
+ sameSite,
+ path: "/",
+ maxAge: COOKIE_MAX_AGE,
+ });
+};
+
+export const deleteSession = async (c: AppContext, db: DatabaseType) => {
+ const sessionId = await getSessionId(c);
+
+ if (!sessionId) {
+ return;
+ }
+
+ deleteCookie(c, SESSION_COOKIE_NAME);
+
+ await db.delete(schema.sessions).where(eq(schema.sessions.id, sessionId));
+};
+
+/**
+ * Middleware to add the current user to the context
+ * - If no session cookie is found, sets `currentUser` to null
+ * - If session cookie is found, but user is not found, sets `currentUser` to null
+ * - If session cookie is found, and user is found, sets `currentUser` on context
+ */
+export const addCurrentUserToContext = async (c: AppContext, next: Next) => {
+ const db = c.get("db");
+
+ let sessionId: string | false | undefined;
+ try {
+ sessionId = await getSignedCookie(
+ c,
+ c.env.SESSION_SECRET,
+ SESSION_COOKIE_NAME,
+ );
+ } catch (_e) {
+ sessionId = undefined;
+ }
+
+ if (!sessionId) {
+ c.set("currentUser", null);
+ return next();
+ }
+
+ const user = await getUserBySessionId(db, sessionId);
+
+ c.set("currentUser", user);
+
+ await next();
+};
+
+/**
+ * Middleware to authenticate a user by session cookie
+ * - If no session cookie is found, returns 401 Unauthorized
+ * - If session cookie is found, but user is not found, returns 401 Unauthorized
+ * - If session cookie is found, and user is found, sets `currentUser` on context
+ */
+export const dashboardAuthentication = async (c: AppContext, next: Next) => {
+ const db = c.get("db");
+
+ const sessionId = await getSessionId(c);
+
+ if (!sessionId) {
+ return c.json({ message: "Unauthorized" }, 401);
+ }
+
+ const user = await getUserBySessionId(db, sessionId);
+
+ if (!user) {
+ return c.json({ message: "Unauthorized" }, 401);
+ }
+
+ if (!user.allowed) {
+ return c.json({ message: "Unauthorized" }, 401);
+ }
+
+ c.set("currentUser", user);
+
+ await next();
+};
+
+export const getUserBySessionId = async (
+ db: DatabaseType,
+ sessionId: string,
+): Promise => {
+ // First, find the session to get the user ID
+ const [session] = await db
+ .select()
+ .from(schema.sessions)
+ .where(eq(schema.sessions.id, sessionId));
+
+ if (!session) {
+ return null;
+ }
+
+ // Now, find the user by the user ID from the session
+ const [user] = await db
+ .select()
+ .from(schema.users)
+ .where(eq(schema.users.id, session.userId));
+
+ return user ?? null;
+};
+
+export const getSessionId = async (c: AppContext) => {
+ return await getSignedCookie(c, c.env.SESSION_SECRET, SESSION_COOKIE_NAME);
+};
diff --git a/lilo/lilo-worker/src/queries/index.ts b/lilo/lilo-worker/src/queries/index.ts
new file mode 100644
index 000000000..a956454cf
--- /dev/null
+++ b/lilo/lilo-worker/src/queries/index.ts
@@ -0,0 +1,5 @@
+export {
+ listProjects,
+ createProject,
+ updateProject,
+} from "./projects";
diff --git a/lilo/lilo-worker/src/queries/projects.ts b/lilo/lilo-worker/src/queries/projects.ts
new file mode 100644
index 000000000..2a375b36a
--- /dev/null
+++ b/lilo/lilo-worker/src/queries/projects.ts
@@ -0,0 +1,40 @@
+import { eq } from "drizzle-orm";
+import * as schema from "../db/schema";
+import type { DatabaseType } from "../types";
+
+/**
+ * List all projects for a user
+ */
+export const listProjects = async (db: DatabaseType, userId: string) => {
+ return db
+ .select()
+ .from(schema.projects)
+ .where(eq(schema.projects.userId, userId));
+};
+
+// TODO - Do we need to omit the `id`?
+type NewProject = typeof schema.projects.$inferInsert;
+type UpdateProject = Partial;
+
+/**
+ * Create a new project
+ */
+export const createProject = async (db: DatabaseType, project: NewProject) => {
+ return db.insert(schema.projects).values(project).returning();
+};
+
+export const updateProject = async (
+ db: DatabaseType,
+ projectId: string,
+ project: UpdateProject,
+) => {
+ return db
+ .update(schema.projects)
+ .set(project)
+ .where(eq(schema.projects.id, projectId))
+ .returning();
+};
+
+export const deleteProject = async (db: DatabaseType, projectId: string) => {
+ return db.delete(schema.projects).where(eq(schema.projects.id, projectId));
+};
diff --git a/lilo/lilo-worker/src/routes/external/api.ts b/lilo/lilo-worker/src/routes/external/api.ts
new file mode 100644
index 000000000..29e1f7b96
--- /dev/null
+++ b/lilo/lilo-worker/src/routes/external/api.ts
@@ -0,0 +1,16 @@
+import { OpenAPIHono } from "@hono/zod-openapi";
+import { apiAuthenticate } from "../../lib/api-authenticate";
+import type { AppType } from "../../types";
+import { projectsRouter } from "./projects";
+import { queriesRouter } from "./queries";
+
+const router = new OpenAPIHono();
+router.use(apiAuthenticate);
+router.route("/projects", projectsRouter);
+router.route("/projects/:projectId/queries", queriesRouter);
+router.openAPIRegistry.registerComponent("securitySchemes", "Bearer", {
+ type: "http",
+ scheme: "bearer",
+});
+
+export { router as externalApiRouter };
diff --git a/lilo/lilo-worker/src/routes/external/index.ts b/lilo/lilo-worker/src/routes/external/index.ts
new file mode 100644
index 000000000..6373252fd
--- /dev/null
+++ b/lilo/lilo-worker/src/routes/external/index.ts
@@ -0,0 +1 @@
+export { externalApiRouter } from "./api";
diff --git a/lilo/lilo-worker/src/routes/external/projects.ts b/lilo/lilo-worker/src/routes/external/projects.ts
new file mode 100644
index 000000000..dee66f99d
--- /dev/null
+++ b/lilo/lilo-worker/src/routes/external/projects.ts
@@ -0,0 +1,142 @@
+import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
+import { eq } from "drizzle-orm";
+import { drizzle } from "drizzle-orm/d1";
+import * as schema from "../../db/schema";
+import { createProject, listProjects } from "../../queries/projects";
+import type { AppType } from "../../types";
+
+const router = new OpenAPIHono();
+
+const ProjectSchema = z
+ .object({
+ id: z.string().openapi({
+ example: "123e4567-e89b-12d3-a456-426614174000",
+ description: "Project ID",
+ }),
+ name: z.string().openapi({
+ example: "My External API",
+ description: "Project name",
+ }),
+ userId: z.string().openapi({
+ example: "123e4567-e89b-12d3-a456-426614174000",
+ description: "Owner's user ID",
+ }),
+ })
+ .openapi("Project");
+
+const CreateProjectSchema = z
+ .object({
+ name: z.string().openapi({
+ example: "My API Project",
+ description: "Name for the new project",
+ }),
+ spec: z.string().openapi({
+ example: "openapi: 3.0.0\ninfo:\n title: API",
+ description: "OpenAPI specification content",
+ }),
+ })
+ .openapi("CreateProject");
+
+const listProjectsRoute = createRoute({
+ method: "get",
+ path: "/",
+ responses: {
+ 200: {
+ content: {
+ "application/json": {
+ schema: z.array(ProjectSchema),
+ },
+ },
+ description: "List of projects",
+ },
+ },
+});
+
+// Define routes
+const createProjectRoute = createRoute({
+ method: "post",
+ path: "/",
+ request: {
+ body: {
+ content: {
+ "application/json": {
+ schema: CreateProjectSchema,
+ },
+ },
+ },
+ },
+ responses: {
+ 201: {
+ content: {
+ "application/json": {
+ schema: ProjectSchema,
+ },
+ },
+ description: "Project created successfully",
+ },
+ },
+});
+
+const updateProjectRoute = createRoute({
+ method: "patch",
+ path: "/{id}",
+ request: {
+ params: z.object({
+ id: z.string(),
+ }),
+ body: {
+ content: {
+ "application/json": {
+ schema: z.object({
+ name: z.string(),
+ }),
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ content: {
+ "application/json": {
+ schema: ProjectSchema,
+ },
+ },
+ description: "Project updated successfully",
+ },
+ },
+});
+
+router.openapi(listProjectsRoute, async (c) => {
+ const db = c.get("db");
+ const userId = c.get("currentUser")?.id ?? "";
+
+ const projects = await listProjects(db, userId);
+
+ return c.json(projects);
+});
+
+router.openapi(createProjectRoute, async (c) => {
+ const db = c.get("db");
+ const { name, spec } = c.req.valid("json");
+ const userId = c.get("currentUser")?.id ?? "";
+
+ const [newProject] = await createProject(db, { name, spec, userId });
+
+ return c.json(newProject, 201);
+});
+
+router.openapi(updateProjectRoute, async (c) => {
+ const db = drizzle(c.env.DB);
+ const id = c.req.valid("param").id;
+ const { name } = c.req.valid("json");
+
+ const [updatedProject] = await db
+ .update(schema.projects)
+ .set({ name })
+ .where(eq(schema.projects.id, id))
+ .returning();
+
+ return c.json(updatedProject);
+});
+
+export { router as projectsRouter };
diff --git a/lilo/lilo-worker/src/routes/external/queries.ts b/lilo/lilo-worker/src/routes/external/queries.ts
new file mode 100644
index 000000000..f8207403e
--- /dev/null
+++ b/lilo/lilo-worker/src/routes/external/queries.ts
@@ -0,0 +1,159 @@
+import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
+import * as schema from "../../db/schema";
+import type { AppType } from "../../types";
+
+const router = new OpenAPIHono();
+
+// Define schemas
+const QuerySchema = z
+ .object({
+ uuid: z.string().uuid().openapi({
+ example: "123e4567-e89b-12d3-a456-426614174000",
+ description: "Query UUID",
+ }),
+ content: z.string().openapi({
+ example: "SELECT * FROM users",
+ description: "Query content",
+ }),
+ queriedBy: z.string().openapi({
+ example: "user@example.com",
+ description: "Email of user who created the query",
+ }),
+ status: z.enum(["pending", "completed", "failed"]).openapi({
+ example: "pending",
+ description: "Current status of the query",
+ }),
+ })
+ .openapi("Query");
+
+const CreateQuerySchema = z
+ .object({
+ content: z.string().openapi({
+ example: "SELECT * FROM users",
+ description: "Query to execute",
+ }),
+ })
+ .openapi("CreateQuery");
+
+// Define routes
+const submitQueryRoute = createRoute({
+ method: "post",
+ path: "/",
+ request: {
+ body: {
+ content: {
+ "application/json": {
+ schema: CreateQuerySchema,
+ },
+ },
+ },
+ },
+ responses: {
+ 202: {
+ content: {
+ "application/json": {
+ schema: QuerySchema,
+ },
+ },
+ description: "Query submitted successfully",
+ },
+ },
+});
+
+const getQueryRoute = createRoute({
+ method: "get",
+ path: "/{queryId}",
+ request: {
+ params: z.object({
+ queryId: z.string().uuid().openapi({
+ description: "Query UUID",
+ example: "123e4567-e89b-12d3-a456-426614174000",
+ }),
+ }),
+ },
+ responses: {
+ 200: {
+ content: {
+ "application/json": {
+ schema: QuerySchema,
+ },
+ },
+ description: "Query details retrieved",
+ },
+ 404: {
+ content: {
+ "application/json": {
+ schema: z.object({
+ error: z.string(),
+ }),
+ },
+ },
+ description: "Query not found",
+ },
+ },
+});
+
+const listQueriesRoute = createRoute({
+ method: "get",
+ path: "/",
+ responses: {
+ 200: {
+ content: {
+ "application/json": {
+ schema: z.array(QuerySchema),
+ },
+ },
+ description: "List of queries",
+ },
+ },
+});
+
+// Implement handlers
+router.openapi(submitQueryRoute, async (c) => {
+ const { content } = c.req.valid("json");
+
+ // TODO: Implement query submission logic
+ const uuid = crypto.randomUUID();
+ const queriedBy = "user@example.com"; // Get from auth context
+
+ return c.json(
+ {
+ uuid,
+ content,
+ queriedBy,
+ status: "pending" as const,
+ },
+ 202,
+ );
+});
+
+router.openapi(getQueryRoute, async (c) => {
+ const { queryId } = c.req.valid("param");
+
+ // TODO: Implement query retrieval logic
+ const query = {
+ uuid: queryId,
+ content: "SELECT * FROM users",
+ queriedBy: "user@example.com",
+ status: "completed" as const,
+ };
+
+ return c.json(query);
+});
+
+router.openapi(listQueriesRoute, async (c) => {
+ const db = c.get("db");
+ const queries = await db.select().from(schema.queries);
+
+ // Map the database results to the expected schema
+ const formattedQueries = queries.map((query) => ({
+ uuid: query.id, // Assuming 'id' is the UUID
+ content: query.query, // Assuming 'query' is the content
+ queriedBy: "user@example.com", // Replace with actual queriedBy if available
+ status: "completed" as const, // Replace with actual status if available
+ }));
+
+ return c.json(formattedQueries, 200);
+});
+
+export { router as queriesRouter };
diff --git a/lilo/lilo-worker/src/routes/internal/api/api-keys.ts b/lilo/lilo-worker/src/routes/internal/api/api-keys.ts
new file mode 100644
index 000000000..f4392f95e
--- /dev/null
+++ b/lilo/lilo-worker/src/routes/internal/api/api-keys.ts
@@ -0,0 +1,100 @@
+import { zValidator } from "@hono/zod-validator";
+import { eq } from "drizzle-orm";
+import { Hono } from "hono";
+import * as jose from "jose";
+import { z } from "zod";
+import * as schema from "../../../db/schema";
+import { importKey } from "../../../lib/crypto";
+import { createJwtPayload } from "../../../lib/jwt";
+import type { AppContext, AppType } from "../../../types";
+
+const createApiKeyBodySchema = z.object({
+ name: z.string(),
+});
+
+export type ApiKeysRouter = typeof apiKeysRouter;
+
+const apiKeysRouter = new Hono()
+ .get("/", getApiKeys)
+ // NOTE - `client.index[":id"].$delete` did not work on the Hono RPC client, so I added the "/keys" prefix
+ .delete("/:id", deleteApiKey)
+ // NOTE - We need to write this handler inline so that type inference works with zValidator and the `valid` property
+ .post("/", zValidator("json", createApiKeyBodySchema), async (c) => {
+ const db = c.get("db");
+ const { name } = c.req.valid("json");
+
+ // Get the authenticated user's information
+ const user = c.get("currentUser");
+
+ if (!user) {
+ return c.json({ error: "Unauthorized" }, 401);
+ }
+
+ // We are going to sign the JWT using the private key from environment variables
+ const privateKey = await importKey("private", c.env.PRIVATE_KEY);
+
+ // Create a JWT payload
+ const payload = createJwtPayload(user?.id);
+
+ // Generate a JWT token bound to the user
+ const token = await new jose.SignJWT(payload)
+ .setProtectedHeader({ alg: "PS256" })
+ .sign(privateKey);
+
+ // Store the API key in the database
+ // TODO - Only store truncated token in the database?
+ await db.insert(schema.apiKeys).values({
+ key: token,
+ userId: user.id,
+ name,
+ });
+
+ return c.json(
+ {
+ token,
+ name,
+ // createdAt: payload.createdAt,
+ createdBy: user.email,
+ },
+ 201,
+ );
+ });
+
+async function getApiKeys(c: AppContext) {
+ const db = c.get("db");
+ const apiKeys = await db.select().from(schema.apiKeys);
+
+ // Transform the DB results to match the expected response format
+ const formattedKeys = apiKeys.map((key) => ({
+ id: key.id,
+ token: maskToken(key.key),
+ name: key.name,
+ createdAt: key.createdAt,
+ createdBy: key.userId,
+ }));
+
+ return c.json(formattedKeys, 200);
+}
+
+/**
+ * Delete an API key for a user
+ */
+async function deleteApiKey(c: AppContext) {
+ const db = c.get("db");
+ const id = c.req.param("id");
+
+ // Delete the API key from the database to revoke it
+ // TODO - Mark the key as revoked instead of fully deleting the record
+ await db.delete(schema.apiKeys).where(eq(schema.apiKeys.id, id));
+
+ return c.body(null, 204);
+}
+
+/**
+ * Mask the token to only show the first and last 4 characters
+ */
+const maskToken = (token: string) => {
+ return `${token.slice(0, 4)}...${token.slice(-4)}`;
+};
+
+export { apiKeysRouter };
diff --git a/lilo/lilo-worker/src/routes/internal/api/api.ts b/lilo/lilo-worker/src/routes/internal/api/api.ts
new file mode 100644
index 000000000..e6fa6c664
--- /dev/null
+++ b/lilo/lilo-worker/src/routes/internal/api/api.ts
@@ -0,0 +1,16 @@
+import { Hono } from "hono";
+import {
+ dashboardAuthentication,
+ requireSessionSecret,
+} from "../../../lib/session-auth";
+import type { AppType } from "../../../types";
+import { apiKeysRouter } from "./api-keys";
+import { projectsRouter } from "./projects";
+
+const router = new Hono()
+ .use(requireSessionSecret)
+ .use(dashboardAuthentication)
+ .route("/projects", projectsRouter)
+ .route("/api-keys", apiKeysRouter);
+
+export { router as internalApiRouter };
diff --git a/lilo/lilo-worker/src/routes/internal/api/index.ts b/lilo/lilo-worker/src/routes/internal/api/index.ts
new file mode 100644
index 000000000..51d431f63
--- /dev/null
+++ b/lilo/lilo-worker/src/routes/internal/api/index.ts
@@ -0,0 +1,3 @@
+export { internalApiRouter } from "./api";
+export type { ProjectsRouter } from "./projects";
+export type { ApiKeysRouter } from "./api-keys";
diff --git a/lilo/lilo-worker/src/routes/internal/api/projects.ts b/lilo/lilo-worker/src/routes/internal/api/projects.ts
new file mode 100644
index 000000000..8f3f44c18
--- /dev/null
+++ b/lilo/lilo-worker/src/routes/internal/api/projects.ts
@@ -0,0 +1,57 @@
+import { zValidator } from "@hono/zod-validator";
+import { Hono } from "hono";
+import { z } from "zod";
+import { createProject, listProjects, updateProject } from "../../../queries";
+import { deleteProject } from "../../../queries/projects";
+import type { AppType } from "../../../types";
+
+const CreateProjectSchema = z.object({
+ name: z.string().min(1, "Project name is required"),
+ spec: z.string().min(1, "Specification is required"),
+});
+
+const UpdateProjectSchema = z.object({
+ name: z.string().min(1, "Project name is required"),
+});
+
+export type ProjectsRouter = typeof projectsRouter;
+
+const projectsRouter = new Hono()
+ .get("/", async (c) => {
+ const db = c.get("db");
+ // TODO - How do we validate that the currentUser is logged in?
+ const userId = c.get("currentUser")?.id ?? "";
+
+ const projects = await listProjects(db, userId);
+
+ return c.json(projects);
+ })
+ .post("/", zValidator("json", CreateProjectSchema), async (c) => {
+ const db = c.get("db");
+ const { name, spec } = c.req.valid("json");
+ // TODO - How do we validate that the currentUser is logged in?
+ const userId = c.get("currentUser")?.id ?? "";
+ console.log("userId", c.get("currentUser"), userId);
+ const newProject = await createProject(db, { name, spec, userId });
+
+ return c.json(newProject, 201);
+ })
+ .patch("/:id", zValidator("json", UpdateProjectSchema), async (c) => {
+ const db = c.get("db");
+ const id = c.req.param("id");
+ const { name } = c.req.valid("json");
+
+ const updatedProject = await updateProject(db, id, { name });
+
+ return c.json(updatedProject);
+ })
+ .delete("/:id", async (c) => {
+ const db = c.get("db");
+ const id = c.req.param("id");
+
+ await deleteProject(db, id);
+
+ return c.json({ message: "Project deleted" });
+ });
+
+export { projectsRouter };
diff --git a/lilo/lilo-worker/src/routes/internal/auth.ts b/lilo/lilo-worker/src/routes/internal/auth.ts
new file mode 100644
index 000000000..90bf55b2a
--- /dev/null
+++ b/lilo/lilo-worker/src/routes/internal/auth.ts
@@ -0,0 +1,125 @@
+import { githubAuth } from "@hono/oauth-providers/github";
+import { eq } from "drizzle-orm";
+import { Hono } from "hono";
+import { HTTPException } from "hono/http-exception";
+import * as schema from "../../db/schema";
+import {
+ createSession,
+ deleteSession,
+ getSessionId,
+} from "../../lib/session-auth";
+import type { AppType } from "../../types";
+
+export type DashboardAuthClient = typeof dashboardAuthRouter;
+
+export const dashboardAuthRouter = new Hono().get(
+ "/session",
+ async (c) => {
+ const sessionId = await getSessionId(c);
+ if (!sessionId) {
+ return c.json({ message: "No session" }, 401);
+ }
+
+ const db = c.get("db");
+ const [result] = await db
+ .select()
+ .from(schema.sessions)
+ .where(eq(schema.sessions.id, sessionId))
+ .innerJoin(schema.users, eq(schema.sessions.userId, schema.users.id));
+
+ if (!result) {
+ return c.json({ message: "Session not found" }, 401);
+ }
+
+ const session = result.sessions;
+ if (!session || new Date(session.expiresAt) < new Date()) {
+ await deleteSession(c, db);
+ return c.json({ message: "Session expired" }, 401);
+ }
+
+ return c.json(result.users);
+ },
+);
+
+// NOTE - Never serve the auth routes if SESSION_SECRET is not set
+dashboardAuthRouter.use("/auth", async (c, next) => {
+ if (!c.env.SESSION_SECRET) {
+ return c.json({ error: "Internal server error" }, 500);
+ }
+ return next();
+});
+
+// Set up GitHub OAuth middleware
+dashboardAuthRouter.use("/github", async (c, next) => {
+ const handler = githubAuth({
+ client_id: c.env.GITHUB_ID,
+ client_secret: c.env.GITHUB_SECRET,
+ scope: ["read:user", "user:email"],
+ oauthApp: true,
+ });
+ return handler(c, next);
+});
+
+// GitHub OAuth callback handler
+dashboardAuthRouter.get("/github", async (c) => {
+ const db = c.get("db");
+ const user = c.get("user-github");
+
+ // TODO - Show an HTML page with a message to the user
+ if (!user?.login || !user?.email) {
+ return c.json({ error: "No user information available" }, 401);
+ }
+
+ const [allowedUser] = await db
+ .select()
+ .from(schema.allowedUsers)
+ .where(eq(schema.allowedUsers.githubUsername, user.login))
+ .limit(1);
+
+ const allowed = !!allowedUser;
+
+ // Upsert the user in the database
+ const [userRecord] = await db
+ .insert(schema.users)
+ .values({
+ email: user.email,
+ githubUsername: user.login,
+ allowed,
+ avatarUrl: user.avatar_url,
+ })
+ .onConflictDoUpdate({
+ target: schema.users.email,
+ set: {
+ githubUsername: user.login,
+ avatarUrl: user.avatar_url,
+ allowed,
+ },
+ })
+ .returning();
+
+ // Generate a session and attach to cookie (stored in the database)
+ await createSession(c, db, userRecord.id);
+
+ // HACK - Redirect to the local SPA dashboard if we're in local mode
+ if (c.env.LILO_ENV === "local") {
+ return c.redirect("http://localhost:3005/");
+ }
+ return c.redirect("/");
+});
+
+// Logout handler
+dashboardAuthRouter.get("/logout", async (c) => {
+ await deleteSession(c, c.get("db"));
+ return c.redirect("/");
+});
+
+// Handle errors from GitHub OAuth
+dashboardAuthRouter.onError((err, c) => {
+ if (err instanceof HTTPException) {
+ if (err.status === 401) {
+ return c.json({ error: "Authentication failed" }, 401);
+ }
+ return err.getResponse();
+ }
+ return c.json({ error: "Internal server error" }, 500);
+});
diff --git a/lilo/lilo-worker/src/routes/internal/index.ts b/lilo/lilo-worker/src/routes/internal/index.ts
new file mode 100644
index 000000000..41fe62fe2
--- /dev/null
+++ b/lilo/lilo-worker/src/routes/internal/index.ts
@@ -0,0 +1,4 @@
+export { internalApiRouter } from "./api";
+export { dashboardAuthRouter, type DashboardAuthClient } from "./auth";
+export type { ProjectsRouter } from "./api/projects";
+export type { ApiKeysRouter } from "./api/api-keys";
diff --git a/lilo/lilo-worker/src/routes/reference.ts b/lilo/lilo-worker/src/routes/reference.ts
new file mode 100644
index 000000000..86d8d4984
--- /dev/null
+++ b/lilo/lilo-worker/src/routes/reference.ts
@@ -0,0 +1,48 @@
+import { apiReference } from "@scalar/hono-api-reference";
+import { eq } from "drizzle-orm";
+import { Hono } from "hono";
+import * as schema from "../db/schema";
+import { addCurrentUserToContext } from "../lib/session-auth";
+import type { AppType } from "../types";
+
+const app = new Hono();
+
+app.get("/", addCurrentUserToContext, async (c, next) => {
+ let apiKey = "";
+ const db = c.get("db");
+ const currentUser = c.get("currentUser");
+ if (currentUser) {
+ apiKey =
+ (await db
+ .select()
+ .from(schema.apiKeys)
+ .where(eq(schema.apiKeys.userId, currentUser.id))
+ .then((res) => res[0]?.key)) ?? "";
+ }
+
+ const reference = apiReference({
+ spec: {
+ url: "/doc", // URL to your OpenAPI specification
+ },
+ // Optional: choose a theme like 'default', 'moon', 'purple', etc.
+ theme: "purple",
+ pageTitle: "Lilo API Reference",
+ authentication: {
+ http: {
+ // NOTE - Need to specify basic, even though we don't use it
+ basic: {
+ username: "",
+ password: "",
+ },
+ bearer: {
+ token: apiKey,
+ },
+ },
+ },
+ });
+
+ // @ts-expect-error - TODO: fix this to incorporate the variables set by the scalar middleware
+ return reference(c, next);
+});
+
+export { app as apiReferenceRouter };
diff --git a/lilo/lilo-worker/src/types.ts b/lilo/lilo-worker/src/types.ts
new file mode 100644
index 000000000..1013edcb5
--- /dev/null
+++ b/lilo/lilo-worker/src/types.ts
@@ -0,0 +1,34 @@
+import type { DrizzleD1Database } from "drizzle-orm/d1";
+import type { Context } from "hono";
+import type * as schema from "./db/schema";
+import type { User } from "./db/schema";
+
+export type DatabaseType = DrizzleD1Database & {
+ $client: D1Database;
+};
+
+export type Bindings = {
+ // D1 database (added as binding in wrangler.toml)
+ DB: D1Database;
+ // GitHub OAuth app credentials
+ GITHUB_ID: string;
+ GITHUB_SECRET: string;
+ // Public key for signing JWT tokens
+ PUBLIC_KEY: string;
+ // Private key for signing JWT tokens
+ PRIVATE_KEY: string;
+ // Session secret for signing cookies
+ SESSION_SECRET: string;
+ // Environment
+ LILO_ENV: string;
+};
+
+export type AppType = {
+ Bindings: Bindings;
+ Variables: {
+ db: DatabaseType;
+ currentUser: User | null;
+ };
+};
+
+export type AppContext = Context;
diff --git a/lilo/lilo-worker/tsconfig.json b/lilo/lilo-worker/tsconfig.json
new file mode 100644
index 000000000..612fe2c12
--- /dev/null
+++ b/lilo/lilo-worker/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "strict": true,
+ "skipLibCheck": true,
+ "lib": ["ESNext"],
+ "types": ["@cloudflare/workers-types"],
+ "jsx": "react-jsx",
+ "jsxImportSource": "hono/jsx"
+ }
+}
diff --git a/lilo/lilo-worker/wrangler.toml b/lilo/lilo-worker/wrangler.toml
new file mode 100644
index 000000000..9a2df4b9a
--- /dev/null
+++ b/lilo/lilo-worker/wrangler.toml
@@ -0,0 +1,34 @@
+name = "lilo-worker"
+compatibility_date = "2024-11-11"
+compatibility_flags = [ "nodejs_compat" ]
+
+assets = { directory = "./public/" }
+
+[dev]
+port = 6246
+
+[[d1_databases]]
+binding = "DB"
+database_name = "lilo-d1-database"
+database_id = "4c6ea673-563f-477a-80d5-319ddaa54189"
+migrations_dir = "drizzle/migrations"
+
+# [vars]
+# MY_VAR = "my-variable"
+
+# Workers Logs
+# Docs: https://developers.cloudflare.com/workers/observability/logs/workers-logs/
+# Configuration: https://developers.cloudflare.com/workers/observability/logs/workers-logs/#enable-workers-logs
+[observability]
+enabled = true
+
+# [[kv_namespaces]]
+# binding = "MY_KV_NAMESPACE"
+# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+
+# [[r2_buckets]]
+# binding = "MY_BUCKET"
+# bucket_name = "my-bucket"
+
+# [ai]
+# binding = "AI"
diff --git a/package.json b/package.json
index 9ff4d00a0..9565a1213 100644
--- a/package.json
+++ b/package.json
@@ -8,13 +8,19 @@
"build:types": "pnpm --filter @fiberplane/fpx-types build",
"build:source-analysis": "pnpm --filter @fiberplane/source-analysis build",
"build:fpx-studio": "pnpm clean:fpx-studio && pnpm build:api && pnpm build:frontend",
+ "build:lilo": "pnpm clean:lilo && pnpm build:lilo-frontend",
+ "build:lilo-frontend": "pnpm --filter lilo-frontend build && cp -r lilo/lilo-frontend/dist lilo/lilo-worker/public",
"build:api": "pnpm --filter @fiberplane/studio build",
"build:www": "pnpm --filter www build",
"build:frontend": "pnpm --filter @fiberplane/studio-frontend build && cp -r studio/dist/* api/dist",
+ "deploy:lilo": "pnpm build:lilo && pnpm --filter lilo-worker run deploy",
"dev:api": "pnpm --filter @fiberplane/studio dev",
"dev:www": "pnpm --filter www dev",
"dev:frontend": "pnpm --filter @fiberplane/studio-frontend dev",
"clean:fpx-studio": "pnpm clean:api && pnpm clean:frontend",
+ "clean:lilo": "pnpm clean:lilo-worker && pnpm clean:lilo-frontend",
+ "clean:lilo-worker": "rimraf lilo/lilo-worker/public",
+ "clean:lilo-frontend": "rimraf lilo/lilo-frontend/dist",
"clean:api": "rimraf api/dist",
"clean:frontend": "rimraf studio/dist",
"format": "biome check . --write",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a0dd0bf95..482df08f6 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -405,7 +405,7 @@ importers:
version: 4.19.2
vitest:
specifier: ^2.1.6
- version: 2.1.6(@types/node@22.10.1)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
+ version: 2.1.6(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
zod:
specifier: ^3.23.8
version: 3.23.8
@@ -417,8 +417,8 @@ importers:
specifier: ^4.20241112.0
version: 4.20241112.0
drizzle-kit:
- specifier: ^0.24.2
- version: 0.24.2
+ specifier: ^0.30.0
+ version: 0.30.0
wrangler:
specifier: ^3.91.0
version: 3.91.0(@cloudflare/workers-types@4.20241112.0)
@@ -456,8 +456,8 @@ importers:
specifier: ^16.4.7
version: 16.4.7
drizzle-kit:
- specifier: ^0.24.2
- version: 0.24.2
+ specifier: ^0.30.0
+ version: 0.30.0
drizzle-orm:
specifier: ^0.33.0
version: 0.33.0(@cloudflare/workers-types@4.20241205.0)(@libsql/client@0.14.0)(@neondatabase/serverless@0.10.4)(@opentelemetry/api@1.9.0)(@types/pg@8.11.10)(@types/react@18.3.12)(react@18.3.1)
@@ -514,6 +514,158 @@ importers:
specifier: ^3.94.0
version: 3.94.0(@cloudflare/workers-types@4.20241205.0)
+ lilo/lilo-frontend:
+ dependencies:
+ '@radix-ui/react-avatar':
+ specifier: ^1.1.1
+ version: 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-dialog':
+ specifier: ^1.1.2
+ version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-dropdown-menu':
+ specifier: ^2.1.2
+ version: 2.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-label':
+ specifier: ^2.1.0
+ version: 2.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot':
+ specifier: ^1.1.0
+ version: 1.1.0(@types/react@18.3.12)(react@18.3.1)
+ '@radix-ui/react-toast':
+ specifier: ^1.2.2
+ version: 1.2.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@tanstack/react-query':
+ specifier: ^5.61.5
+ version: 5.61.5(react@18.3.1)
+ class-variance-authority:
+ specifier: ^0.7.1
+ version: 0.7.1
+ clsx:
+ specifier: ^2.1.1
+ version: 2.1.1
+ hono:
+ specifier: ^4.6.13
+ version: 4.6.13
+ lucide-react:
+ specifier: ^0.468.0
+ version: 0.468.0(react@18.3.1)
+ react:
+ specifier: ^18.3.1
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.3.1
+ version: 18.3.1(react@18.3.1)
+ tailwind-merge:
+ specifier: ^2.5.5
+ version: 2.5.5
+ tailwindcss-animate:
+ specifier: ^1.0.7
+ version: 1.0.7(tailwindcss@3.4.15)
+ devDependencies:
+ '@cloudflare/workers-types':
+ specifier: ^4.20241205.0
+ version: 4.20241205.0
+ '@types/node':
+ specifier: ^22.10.2
+ version: 22.10.2
+ '@types/react':
+ specifier: ^18.3.12
+ version: 18.3.12
+ '@types/react-dom':
+ specifier: ^18.3.1
+ version: 18.3.1
+ '@vitejs/plugin-react':
+ specifier: ^4.3.4
+ version: 4.3.4(vite@6.0.1(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1))
+ autoprefixer:
+ specifier: ^10.4.20
+ version: 10.4.20(postcss@8.4.49)
+ globals:
+ specifier: ^15.12.0
+ version: 15.13.0
+ postcss:
+ specifier: ^8.4.49
+ version: 8.4.49
+ tailwindcss:
+ specifier: ^3.4.15
+ version: 3.4.15
+ typescript:
+ specifier: ~5.6.2
+ version: 5.6.2
+ vite:
+ specifier: ^6.0.1
+ version: 6.0.1(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
+
+ lilo/lilo-worker:
+ dependencies:
+ '@ai-sdk/google':
+ specifier: ^1.0.9
+ version: 1.0.9(zod@3.24.0)
+ '@ai-sdk/openai':
+ specifier: ^1.0.8
+ version: 1.0.8(zod@3.24.0)
+ '@fiberplane/embedded':
+ specifier: ^0.0.9
+ version: 0.0.9
+ '@hono/oauth-providers':
+ specifier: ^0.6.2
+ version: 0.6.2(hono@4.6.13)
+ '@hono/zod-openapi':
+ specifier: ^0.18.0
+ version: 0.18.3(hono@4.6.13)(zod@3.24.0)
+ '@hono/zod-validator':
+ specifier: ^0.4.1
+ version: 0.4.1(hono@4.6.13)(zod@3.24.0)
+ '@scalar/hono-api-reference':
+ specifier: ^0.5.163
+ version: 0.5.163(hono@4.6.13)
+ ai:
+ specifier: ^4.0.16
+ version: 4.0.16(react@18.3.1)(zod@3.24.0)
+ dotenv:
+ specifier: ^16.4.5
+ version: 16.4.7
+ drizzle-orm:
+ specifier: ^0.36.4
+ version: 0.36.4(@cloudflare/workers-types@4.20241205.0)(@libsql/client-wasm@0.14.0)(@libsql/client@0.14.0)(@neondatabase/serverless@0.10.4)(@opentelemetry/api@1.9.0)(@types/pg@8.11.10)(@types/react@18.3.12)(react@18.3.1)
+ hono:
+ specifier: ^4.6.7
+ version: 4.6.13
+ jose:
+ specifier: ^5.9.6
+ version: 5.9.6
+ zod:
+ specifier: ^3.23.8
+ version: 3.24.0
+ devDependencies:
+ '@biomejs/biome':
+ specifier: ^1.9.4
+ version: 1.9.4
+ '@cloudflare/workers-types':
+ specifier: ^4.20241205.0
+ version: 4.20241205.0
+ '@fiberplane/hono-otel':
+ specifier: workspace:*
+ version: link:../../packages/client-library-otel
+ '@libsql/client':
+ specifier: ^0.14.0
+ version: 0.14.0
+ drizzle-kit:
+ specifier: ^0.28.1
+ version: 0.28.1
+ drizzle-seed:
+ specifier: ^0.1.2
+ version: 0.1.2(drizzle-orm@0.36.4(@cloudflare/workers-types@4.20241205.0)(@libsql/client-wasm@0.14.0)(@libsql/client@0.14.0)(@neondatabase/serverless@0.10.4)(@opentelemetry/api@1.9.0)(@types/pg@8.11.10)(@types/react@18.3.12)(react@18.3.1))
+ tsx:
+ specifier: ^4.19.2
+ version: 4.19.2
+ typescript:
+ specifier: ^5.5.4
+ version: 5.7.2
+ wrangler:
+ specifier: ^3.95.0
+ version: 3.95.0(@cloudflare/workers-types@4.20241205.0)
+
packages/client-library-otel:
dependencies:
'@opentelemetry/api':
@@ -573,7 +725,7 @@ importers:
version: 5.7.2
vitest:
specifier: ^1.6.0
- version: 1.6.0(@types/node@22.10.1)(lightningcss@1.28.1)
+ version: 1.6.0(@types/node@22.10.2)(lightningcss@1.28.1)
packages/mcp-server:
dependencies:
@@ -914,13 +1066,13 @@ importers:
version: 3.2.1
'@astrojs/starlight':
specifier: ^0.28.6
- version: 0.28.6(astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))
+ version: 0.28.6(astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))
'@iconify-json/lucide':
specifier: ^1.2.16
version: 1.2.16
astro:
specifier: ^4.16.18
- version: 4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)
+ version: 4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)
astro-icon:
specifier: ^1.1.4
version: 1.1.4
@@ -935,7 +1087,7 @@ importers:
version: 0.32.6
starlight-package-managers:
specifier: ^0.6.0
- version: 0.6.0(@astrojs/starlight@0.28.6(astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)))(astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))
+ version: 0.6.0(@astrojs/starlight@0.28.6(astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)))(astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))
tailwindcss:
specifier: ^3.4.15
version: 3.4.15
@@ -970,6 +1122,12 @@ packages:
peerDependencies:
zod: ^3.0.0
+ '@ai-sdk/google@1.0.9':
+ resolution: {integrity: sha512-fIwKAhMiYCrWDQG3SMUkld3RPKq1yr1yrjFAtjf8Vzp0nKq+DdVtfmnUFFSOawn+rzJLGfhPc42H8ShFX89djQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ zod: ^3.0.0
+
'@ai-sdk/mistral@0.0.42':
resolution: {integrity: sha512-wvtvfXJcyOAWNuc3ZaWogIcTfKyHLw7sudzzyGYb7jHQgZRRlrythuMeoR9OcC4USEKE2xgYyAQ/JF31TZUPKw==}
engines: {node: '>=18'}
@@ -994,6 +1152,12 @@ packages:
peerDependencies:
zod: ^3.0.0
+ '@ai-sdk/openai@1.0.8':
+ resolution: {integrity: sha512-wcTHM9qgRWGYVO3WxPSTN/RwnZ9R5/17xyo61iUCCSCZaAuJyh6fKddO0/oamwDp3BG7g+4wbfAyuTo32H+fHw==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ zod: ^3.0.0
+
'@ai-sdk/provider-utils@1.0.20':
resolution: {integrity: sha512-ngg/RGpnA00eNOWEtXHenpX1MsM2QshQh4QJFjUfwcqHpM5kTfG7je7Rc3HcEDP+OkRVv2GF+X4fC1Vfcnl8Ow==}
engines: {node: '>=18'}
@@ -1021,6 +1185,15 @@ packages:
zod:
optional: true
+ '@ai-sdk/provider-utils@2.0.4':
+ resolution: {integrity: sha512-GMhcQCZbwM6RoZCri0MWeEWXRt/T+uCxsmHEsTwNvEH3GDjNzchfX25C8ftry2MeEOOn6KfqCLSKomcgK6RoOg==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ zod: ^3.0.0
+ peerDependenciesMeta:
+ zod:
+ optional: true
+
'@ai-sdk/provider@0.0.24':
resolution: {integrity: sha512-XMsNGJdGO+L0cxhhegtqZ8+T6nn4EoShS819OvCgI2kLbYTIvk0GWFGD0AXJmxkxs3DrpsJxKAFukFR7bvTkgQ==}
engines: {node: '>=18'}
@@ -1033,6 +1206,10 @@ packages:
resolution: {integrity: sha512-mV+3iNDkzUsZ0pR2jG0sVzU6xtQY5DtSCBy3JFycLp6PwjyLw/iodfL3MwdmMCRJWgs3dadcHejRnMvF9nGTBg==}
engines: {node: '>=18'}
+ '@ai-sdk/provider@1.0.2':
+ resolution: {integrity: sha512-YYtP6xWQyaAf5LiWLJ+ycGTOeBLWrED7LUrvc+SQIWhGaneylqbaGsyQL7VouQUeQ4JZ1qKYZuhmi3W56HADPA==}
+ engines: {node: '>=18'}
+
'@ai-sdk/react@0.0.70':
resolution: {integrity: sha512-GnwbtjW4/4z7MleLiW+TOZC2M29eCg1tOUpuEiYFMmFNZK8mkrqM0PFZMo6UsYeUYMWqEOOcPOU9OQVJMJh7IQ==}
engines: {node: '>=18'}
@@ -1057,6 +1234,18 @@ packages:
zod:
optional: true
+ '@ai-sdk/react@1.0.6':
+ resolution: {integrity: sha512-8Hkserq0Ge6AEi7N4hlv2FkfglAGbkoAXEZ8YSp255c3PbnZz6+/5fppw+aROmZMOfNwallSRuy1i/iPa2rBpQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ react: ^18 || ^19 || ^19.0.0-rc
+ zod: ^3.0.0
+ peerDependenciesMeta:
+ react:
+ optional: true
+ zod:
+ optional: true
+
'@ai-sdk/solid@0.0.54':
resolution: {integrity: sha512-96KWTVK+opdFeRubqrgaJXoNiDP89gNxFRWUp0PJOotZW816AbhUf4EnDjBjXTLjXL1n0h8tGSE9sZsRkj9wQQ==}
engines: {node: '>=18'}
@@ -1093,6 +1282,15 @@ packages:
zod:
optional: true
+ '@ai-sdk/ui-utils@1.0.5':
+ resolution: {integrity: sha512-DGJSbDf+vJyWmFNexSPUsS1AAy7gtsmFmoSyNbNbJjwl9hRIf2dknfA1V0ahx6pg3NNklNYFm53L8Nphjovfvg==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ zod: ^3.0.0
+ peerDependenciesMeta:
+ zod:
+ optional: true
+
'@ai-sdk/vue@0.0.59':
resolution: {integrity: sha512-+ofYlnqdc8c4F6tM0IKF0+7NagZRAiqBJpGDJ+6EYhDW8FHLUP/JFBgu32SjxSxC6IKFZxEnl68ZoP/Z38EMlw==}
engines: {node: '>=18'}
@@ -1442,6 +1640,18 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-react-jsx-self@7.25.9':
+ resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-source@7.25.9':
+ resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-transform-react-jsx@7.25.9':
resolution: {integrity: sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==}
engines: {node: '>=6.9.0'}
@@ -2663,6 +2873,9 @@ packages:
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
engines: {node: '>=14'}
+ '@fiberplane/embedded@0.0.9':
+ resolution: {integrity: sha512-lEmrA3lIQHMlx8FliefZ3l9NszjDrAFxMyw4n69bwotqUVyD2ddbx6Ry8gAULWSYynI3fzbig8ECmJnkb1iGhg==}
+
'@fiberplane/hono-otel@0.3.1':
resolution: {integrity: sha512-E5Gpg06jMngM3gyIjhy4lFuGAv8Qpx0gnglmSgUeuEAkrpAAPy4tHpoFZsFc+gLgoM5+KytoI3MFowgheHjacg==}
@@ -3551,6 +3764,19 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-avatar@1.1.1':
+ resolution: {integrity: sha512-eoOtThOmxeoizxpX6RiEsQZ2wj5r4+zoeqAwO0cBaFQGjJwIH3dIX0OCxNrCyrrdxG+vBweMETh3VziQG7c1kw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-checkbox@1.1.2':
resolution: {integrity: sha512-/i0fl686zaJbDQLNKrkCbMyDm6FQMt4jg323k7HuqitoANm9sE23Ql8yOK3Wusk34HSLKDChhMux05FnP6KUkw==}
peerDependencies:
@@ -4212,6 +4438,12 @@ packages:
resolution: {integrity: sha512-xzvBr1Q1c4lCe7i6sRnrofxeO1QTP/LKQ6A6qy0iB4x5yfiSfARMEQEghojzTNALDTcv8En04qYNIco9/K9eZQ==}
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
+ '@scalar/hono-api-reference@0.5.163':
+ resolution: {integrity: sha512-kIZRMSIBT1Ac0PjWLuoIERZYTk0ZTp+B/zfK13lOjTQ8cgPnau34hsAT8Bydr9hOWENbmEPOumMBFJ1F81+PKw==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ hono: ^4.0.0
+
'@scalar/openapi-parser@0.8.10':
resolution: {integrity: sha512-wAHrxB6SMKqlyOfj2Bq5rPl9s25+0LXD3UsFvx3v35bQSoIS13h0akVgpph5sbwRvufgQoE4IDWYuFTXH393Bg==}
engines: {node: '>=18'}
@@ -4220,6 +4452,10 @@ packages:
resolution: {integrity: sha512-6geH9ehvQ/sG/xUyy3e0lyOw3BaY5s6nn22wHjEJhcobdmWyFER0O6m7AU0ZN4QTjle/gYvFJOjj552l/rsNSw==}
engines: {node: '>=18'}
+ '@scalar/types@0.0.23':
+ resolution: {integrity: sha512-dOvQig4hyeVw1kXIo9MQAnM9tUt9vCOZs3zOe6oSqOUG8xY7+WXioirlRCsc+wcQegMbuNYOlNBXCDugOP1YJA==}
+ engines: {node: '>=18'}
+
'@sevinf/maybe@0.5.0':
resolution: {integrity: sha512-ARhyoYDnY1LES3vYI0fiG6e9esWfTNcXcO6+MPJJXcnyMV3bim4lnFt45VXouV7y82F4x3YH8nOQ6VztuvUiWg==}
@@ -4732,6 +4968,9 @@ packages:
'@types/node@22.10.1':
resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==}
+ '@types/node@22.10.2':
+ resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==}
+
'@types/papaparse@5.3.15':
resolution: {integrity: sha512-JHe6vF6x/8Z85nCX4yFdDslN11d+1pr12E526X8WAfhadOeaOTx5AuIkvDKIBopfvlzpzkdMx4YyvSKCM9oqtw==}
@@ -4845,6 +5084,9 @@ packages:
'@ungap/structured-clone@1.2.0':
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+ '@unhead/schema@1.11.14':
+ resolution: {integrity: sha512-V9W9u5tF1/+TiLqxu+Qvh1ShoMDkPEwHoEo4DKdDG6ko7YlbzFfDxV6el9JwCren45U/4Vy/4Xi7j8OH02wsiA==}
+
'@upstash/vector@1.1.7':
resolution: {integrity: sha512-yxgXdH/Z2uX8XUVrLeo6ZNci2Z8EzXGwjIZ8EZwctF5+oiBIKwz8tsh/yUesyGrbuQ+ViBPGtZWV5vLFbp649w==}
@@ -4853,6 +5095,12 @@ packages:
peerDependencies:
vite: ^4 || ^5 || ^6
+ '@vitejs/plugin-react@4.3.4':
+ resolution: {integrity: sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0 || ^6.0.0
+
'@vitest/expect@1.6.0':
resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==}
@@ -5027,6 +5275,18 @@ packages:
zod:
optional: true
+ ai@4.0.16:
+ resolution: {integrity: sha512-DdpyzTaJYwagQKkWNb1eYx/UcQoMNy+cZVRYYX3cb88r25EI46YjtjMuvDhd296FPgjJBFqbL4IvDHQBPaSwbw==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ react: ^18 || ^19 || ^19.0.0-rc
+ zod: ^3.0.0
+ peerDependenciesMeta:
+ react:
+ optional: true
+ zod:
+ optional: true
+
ai@4.0.7:
resolution: {integrity: sha512-8KWAHZbL2xwQwFqLX/3Cb9+r2xyu0acgYK2xii/kW6l5fl6Bq7Zng+jU7DF7lxNU3M9rf29Gkc0oVrTzkRVJjw==}
engines: {node: '>=18'}
@@ -5905,10 +6165,6 @@ packages:
resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==}
engines: {node: '>=12'}
- drizzle-kit@0.24.2:
- resolution: {integrity: sha512-nXOaTSFiuIaTMhS8WJC2d4EBeIcN9OSt2A2cyFbQYBAZbi7lRsVGJNqDpEwPqYfJz38yxbY/UtbvBBahBfnExQ==}
- hasBin: true
-
drizzle-kit@0.26.2:
resolution: {integrity: sha512-cMq8omEKywjIy5KcqUo6LvEFxkl8/zYHsgYjFVXjmPWWtuW4blcz+YW9+oIhoaALgs2ebRjzXwsJgN9i6P49Dw==}
hasBin: true
@@ -5917,6 +6173,10 @@ packages:
resolution: {integrity: sha512-JimOV+ystXTWMgZkLHYHf2w3oS28hxiH1FR0dkmJLc7GHzdGJoJAQtQS5DRppnabsRZwE2U1F6CuezVBgmsBBQ==}
hasBin: true
+ drizzle-kit@0.30.0:
+ resolution: {integrity: sha512-zAf0qg/BX2lV/Xip4igXrtbDv+Ub8S39U6qSOEGNvqcHrnmaQjS4mkkFZOUsgXRbuH56QUeWZxfnLHefrKCV5g==}
+ hasBin: true
+
drizzle-orm@0.33.0:
resolution: {integrity: sha512-SHy72R2Rdkz0LEq0PSG/IdvnT3nGiWuRk+2tXZQ90GVq/XQhpCzu/EFT3V2rox+w8MlkBQxifF8pCStNYnERfA==}
peerDependencies:
@@ -6277,6 +6537,14 @@ packages:
sqlite3:
optional: true
+ drizzle-seed@0.1.2:
+ resolution: {integrity: sha512-F7+1tK/f5SHXK75ISH1zKUZWslW18dr9gbYB9tQHx7t5Wm82481OE5HGKFIjWuGV1VS0eFVr7+uXl8PFwPJjPA==}
+ peerDependencies:
+ drizzle-orm: '>=0.36.4'
+ peerDependenciesMeta:
+ drizzle-orm:
+ optional: true
+
drizzle-zod@0.5.1:
resolution: {integrity: sha512-C/8bvzUH/zSnVfwdSibOgFjLhtDtbKYmkbPbUCq46QZyZCH6kODIMSOgZ8R7rVjoI+tCj3k06MRJMDqsIeoS4A==}
peerDependencies:
@@ -6828,6 +7096,10 @@ packages:
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
engines: {node: '>=4'}
+ globals@15.13.0:
+ resolution: {integrity: sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==}
+ engines: {node: '>=18'}
+
globby@11.1.0:
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
engines: {node: '>=10'}
@@ -6979,6 +7251,9 @@ packages:
resolution: {integrity: sha512-haV0gaMdSjy9URCRN9hxBPlqHa7fMm/T72kAImIxvw4eQLbNz1rgjN4hHElLJSieDiNuiIAXC//cC6YGz2KCbg==}
engines: {node: '>=16.9.0'}
+ hookable@5.5.3:
+ resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
+
html-entities@2.5.2:
resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==}
@@ -7620,6 +7895,11 @@ packages:
resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==}
engines: {node: 14 || >=16.14}
+ lucide-react@0.468.0:
+ resolution: {integrity: sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA==}
+ peerDependencies:
+ react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc
+
magic-bytes.js@1.10.0:
resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==}
@@ -8224,6 +8504,9 @@ packages:
zod:
optional: true
+ openapi-types@12.1.3:
+ resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==}
+
openapi3-ts@4.4.0:
resolution: {integrity: sha512-9asTNB9IkKEzWMcHmVZE7Ts3kC9G7AFHfs8i7caD8HbI76gEjdkId4z/AkP83xdZsH7PLAnnbl47qZkXuxpArw==}
@@ -8690,6 +8973,9 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
+ pure-rand@6.1.0:
+ resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==}
+
qs@6.11.2:
resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==}
engines: {node: '>=0.6'}
@@ -8780,6 +9066,10 @@ packages:
react-is@18.3.1:
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+ react-refresh@0.14.2:
+ resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
+ engines: {node: '>=0.10.0'}
+
react-remove-scroll-bar@2.3.6:
resolution: {integrity: sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==}
engines: {node: '>=10'}
@@ -10314,6 +10604,16 @@ packages:
'@cloudflare/workers-types':
optional: true
+ wrangler@3.95.0:
+ resolution: {integrity: sha512-3w5852i3FNyDz421K2Qk4v5L8jjwegO5O8E1+VAQmjnm82HFNxpIRUBq0bmM7CTLvOPI/Jjcmj/eAWjQBL7QYg==}
+ engines: {node: '>=16.17.0'}
+ hasBin: true
+ peerDependencies:
+ '@cloudflare/workers-types': ^4.20241205.0
+ peerDependenciesMeta:
+ '@cloudflare/workers-types':
+ optional: true
+
wrap-ansi@6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
@@ -10412,6 +10712,9 @@ packages:
youch@3.3.4:
resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==}
+ zhead@2.2.4:
+ resolution: {integrity: sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==}
+
zod-package-json@1.0.3:
resolution: {integrity: sha512-Mb6GzuRyUEl8X+6V6xzHbd4XV0au/4gOYrYP+CAfHL32uPmGswES+v2YqonZiW1NZWVA3jkssCKSU2knonm/aQ==}
engines: {node: '>=20'}
@@ -10468,6 +10771,12 @@ snapshots:
'@ai-sdk/provider-utils': 2.0.2(zod@3.23.8)
zod: 3.23.8
+ '@ai-sdk/google@1.0.9(zod@3.24.0)':
+ dependencies:
+ '@ai-sdk/provider': 1.0.2
+ '@ai-sdk/provider-utils': 2.0.4(zod@3.24.0)
+ zod: 3.24.0
+
'@ai-sdk/mistral@0.0.42(zod@3.23.8)':
dependencies:
'@ai-sdk/provider': 0.0.24
@@ -10498,6 +10807,12 @@ snapshots:
'@ai-sdk/provider-utils': 2.0.2(zod@3.23.8)
zod: 3.23.8
+ '@ai-sdk/openai@1.0.8(zod@3.24.0)':
+ dependencies:
+ '@ai-sdk/provider': 1.0.2
+ '@ai-sdk/provider-utils': 2.0.4(zod@3.24.0)
+ zod: 3.24.0
+
'@ai-sdk/provider-utils@1.0.20(zod@3.23.8)':
dependencies:
'@ai-sdk/provider': 0.0.24
@@ -10543,6 +10858,15 @@ snapshots:
optionalDependencies:
zod: 3.23.8
+ '@ai-sdk/provider-utils@2.0.4(zod@3.24.0)':
+ dependencies:
+ '@ai-sdk/provider': 1.0.2
+ eventsource-parser: 3.0.0
+ nanoid: 3.3.8
+ secure-json-parse: 2.7.0
+ optionalDependencies:
+ zod: 3.24.0
+
'@ai-sdk/provider@0.0.24':
dependencies:
json-schema: 0.4.0
@@ -10555,6 +10879,10 @@ snapshots:
dependencies:
json-schema: 0.4.0
+ '@ai-sdk/provider@1.0.2':
+ dependencies:
+ json-schema: 0.4.0
+
'@ai-sdk/react@0.0.70(react@18.3.1)(zod@3.23.8)':
dependencies:
'@ai-sdk/provider-utils': 1.0.22(zod@3.23.8)
@@ -10585,6 +10913,16 @@ snapshots:
react: 18.3.1
zod: 3.23.8
+ '@ai-sdk/react@1.0.6(react@18.3.1)(zod@3.24.0)':
+ dependencies:
+ '@ai-sdk/provider-utils': 2.0.4(zod@3.24.0)
+ '@ai-sdk/ui-utils': 1.0.5(zod@3.24.0)
+ swr: 2.2.5(react@18.3.1)
+ throttleit: 2.1.0
+ optionalDependencies:
+ react: 18.3.1
+ zod: 3.24.0
+
'@ai-sdk/solid@0.0.54(zod@3.23.8)':
dependencies:
'@ai-sdk/provider-utils': 1.0.22(zod@3.23.8)
@@ -10647,6 +10985,14 @@ snapshots:
optionalDependencies:
zod: 3.23.8
+ '@ai-sdk/ui-utils@1.0.5(zod@3.24.0)':
+ dependencies:
+ '@ai-sdk/provider': 1.0.2
+ '@ai-sdk/provider-utils': 2.0.4(zod@3.24.0)
+ zod-to-json-schema: 3.23.5(zod@3.24.0)
+ optionalDependencies:
+ zod: 3.24.0
+
'@ai-sdk/vue@0.0.59(vue@3.5.12(typescript@5.7.2))(zod@3.23.8)':
dependencies:
'@ai-sdk/provider-utils': 1.0.22(zod@3.23.8)
@@ -10791,12 +11137,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@astrojs/mdx@3.1.9(astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))':
+ '@astrojs/mdx@3.1.9(astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))':
dependencies:
'@astrojs/markdown-remark': 5.3.0
'@mdx-js/mdx': 3.1.0(acorn@8.14.0)
acorn: 8.14.0
- astro: 4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)
+ astro: 4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)
es-module-lexer: 1.5.4
estree-util-visit: 2.0.0
gray-matter: 4.0.3
@@ -10826,15 +11172,15 @@ snapshots:
stream-replace-string: 2.0.0
zod: 3.24.0
- '@astrojs/starlight@0.28.6(astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))':
+ '@astrojs/starlight@0.28.6(astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))':
dependencies:
- '@astrojs/mdx': 3.1.9(astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))
+ '@astrojs/mdx': 3.1.9(astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))
'@astrojs/sitemap': 3.2.1
'@pagefind/default-ui': 1.2.0
'@types/hast': 3.0.4
'@types/mdast': 4.0.4
- astro: 4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)
- astro-expressive-code: 0.35.6(astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))
+ astro: 4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)
+ astro-expressive-code: 0.35.6(astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))
bcp-47: 2.1.0
hast-util-from-html: 2.0.3
hast-util-select: 6.0.3
@@ -11533,6 +11879,16 @@ snapshots:
'@babel/core': 7.26.0
'@babel/helper-plugin-utils': 7.25.9
+ '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
'@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
@@ -12382,6 +12738,10 @@ snapshots:
'@fastify/busboy@2.1.1': {}
+ '@fiberplane/embedded@0.0.9':
+ dependencies:
+ openapi-types: 12.1.3
+
'@fiberplane/hono-otel@0.3.1':
dependencies:
'@opentelemetry/api': 1.9.0
@@ -12456,6 +12816,10 @@ snapshots:
dependencies:
hono: 4.6.12
+ '@hono/oauth-providers@0.6.2(hono@4.6.13)':
+ dependencies:
+ hono: 4.6.13
+
'@hono/zod-openapi@0.18.3(hono@4.6.12)(zod@3.23.8)':
dependencies:
'@asteasolutions/zod-to-openapi': 7.3.0(zod@3.23.8)
@@ -12470,6 +12834,13 @@ snapshots:
hono: 4.6.12
zod: 3.24.0
+ '@hono/zod-openapi@0.18.3(hono@4.6.13)(zod@3.24.0)':
+ dependencies:
+ '@asteasolutions/zod-to-openapi': 7.3.0(zod@3.24.0)
+ '@hono/zod-validator': 0.4.1(hono@4.6.13)(zod@3.24.0)
+ hono: 4.6.13
+ zod: 3.24.0
+
'@hono/zod-validator@0.2.2(hono@4.6.12)(zod@3.23.8)':
dependencies:
hono: 4.6.12
@@ -12490,6 +12861,11 @@ snapshots:
hono: 4.6.12
zod: 3.24.0
+ '@hono/zod-validator@0.4.1(hono@4.6.13)(zod@3.24.0)':
+ dependencies:
+ hono: 4.6.13
+ zod: 3.24.0
+
'@hookform/resolvers@3.9.1(react-hook-form@7.53.2(react@18.3.1))':
dependencies:
react-hook-form: 7.53.2(react@18.3.1)
@@ -12702,8 +13078,8 @@ snapshots:
p-queue: 6.6.2
p-retry: 4.6.2
uuid: 10.0.0
- zod: 3.23.8
- zod-to-json-schema: 3.23.5(zod@3.23.8)
+ zod: 3.24.0
+ zod-to-json-schema: 3.23.5(zod@3.24.0)
transitivePeerDependencies:
- openai
@@ -12718,8 +13094,8 @@ snapshots:
p-queue: 6.6.2
p-retry: 4.6.2
uuid: 10.0.0
- zod: 3.23.8
- zod-to-json-schema: 3.23.5(zod@3.23.8)
+ zod: 3.24.0
+ zod-to-json-schema: 3.23.5(zod@3.24.0)
transitivePeerDependencies:
- openai
@@ -12864,7 +13240,7 @@ snapshots:
'@llamaindex/core@0.3.7(@aws-crypto/sha256-js@5.2.0)(@xenova/transformers@2.17.2)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.15)(pathe@1.1.2)':
dependencies:
'@llamaindex/env': 0.1.16(@aws-crypto/sha256-js@5.2.0)(@xenova/transformers@2.17.2)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.15)(pathe@1.1.2)
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
magic-bytes.js: 1.10.0
zod: 3.24.0
zod-to-json-schema: 3.23.5(zod@3.24.0)
@@ -13526,6 +13902,18 @@ snapshots:
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
+ '@radix-ui/react-avatar@1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.12
+ '@types/react-dom': 18.3.1
+
'@radix-ui/react-checkbox@1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.0
@@ -14132,6 +14520,11 @@ snapshots:
'@sapphire/snowflake@3.5.5': {}
+ '@scalar/hono-api-reference@0.5.163(hono@4.6.13)':
+ dependencies:
+ '@scalar/types': 0.0.23
+ hono: 4.6.13
+
'@scalar/openapi-parser@0.8.10':
dependencies:
ajv: 8.17.1
@@ -14143,6 +14536,11 @@ snapshots:
'@scalar/openapi-types@0.1.5': {}
+ '@scalar/types@0.0.23':
+ dependencies:
+ '@scalar/openapi-types': 0.1.5
+ '@unhead/schema': 1.11.14
+
'@sevinf/maybe@0.5.0': {}
'@shikijs/core@1.23.1':
@@ -14701,7 +15099,7 @@ snapshots:
dependencies:
'@types/http-cache-semantics': 4.0.4
'@types/keyv': 3.1.4
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
'@types/responselike': 1.0.3
'@types/cookie@0.6.0': {}
@@ -14730,7 +15128,7 @@ snapshots:
'@types/keyv@3.1.4':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
'@types/lodash-es@4.17.12':
dependencies:
@@ -14754,12 +15152,12 @@ snapshots:
'@types/node-fetch@2.6.12':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
form-data: 4.0.1
'@types/node-forge@1.3.11':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
'@types/node@17.0.45': {}
@@ -14779,19 +15177,23 @@ snapshots:
dependencies:
undici-types: 6.20.0
+ '@types/node@22.10.2':
+ dependencies:
+ undici-types: 6.20.0
+
'@types/papaparse@5.3.15':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
'@types/pg@8.11.10':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
pg-protocol: 1.7.0
pg-types: 4.0.2
'@types/pg@8.11.6':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
pg-protocol: 1.7.0
pg-types: 4.0.2
@@ -14810,19 +15212,19 @@ snapshots:
'@types/responselike@1.0.3':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
'@types/retry@0.12.0': {}
'@types/sax@1.2.7':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
'@types/shimmer@1.2.0': {}
'@types/tar@6.1.13':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
minipass: 4.2.8
'@types/tough-cookie@4.0.5': {}
@@ -14849,13 +15251,13 @@ snapshots:
'@types/yauzl@2.10.3':
dependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
optional: true
- '@typescript/vfs@1.6.0(typescript@5.7.2)':
+ '@typescript/vfs@1.6.0(typescript@5.6.2)':
dependencies:
debug: 4.4.0(supports-color@8.1.1)
- typescript: 5.7.2
+ typescript: 5.6.2
transitivePeerDependencies:
- supports-color
@@ -14908,6 +15310,11 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
+ '@unhead/schema@1.11.14':
+ dependencies:
+ hookable: 5.5.3
+ zhead: 2.2.4
+
'@upstash/vector@1.1.7': {}
'@vitejs/plugin-react-swc@3.7.2(@swc/helpers@0.5.13)(vite@6.0.1(@types/node@22.10.0)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1))':
@@ -14917,6 +15324,17 @@ snapshots:
transitivePeerDependencies:
- '@swc/helpers'
+ '@vitejs/plugin-react@4.3.4(vite@6.0.1(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1))':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0)
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.14.2
+ vite: 6.0.1(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
+ transitivePeerDependencies:
+ - supports-color
+
'@vitest/expect@1.6.0':
dependencies:
'@vitest/spy': 1.6.0
@@ -14938,13 +15356,13 @@ snapshots:
optionalDependencies:
vite: 6.0.1(@types/node@22.10.0)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
- '@vitest/mocker@2.1.6(vite@6.0.1(@types/node@22.10.1)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1))':
+ '@vitest/mocker@2.1.6(vite@6.0.1(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1))':
dependencies:
'@vitest/spy': 2.1.6
estree-walker: 3.0.3
magic-string: 0.30.15
optionalDependencies:
- vite: 6.0.1(@types/node@22.10.1)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
+ vite: 6.0.1(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
'@vitest/pretty-format@2.1.6':
dependencies:
@@ -15208,6 +15626,19 @@ snapshots:
- solid-js
- vue
+ ai@4.0.16(react@18.3.1)(zod@3.24.0):
+ dependencies:
+ '@ai-sdk/provider': 1.0.2
+ '@ai-sdk/provider-utils': 2.0.4(zod@3.24.0)
+ '@ai-sdk/react': 1.0.6(react@18.3.1)(zod@3.24.0)
+ '@ai-sdk/ui-utils': 1.0.5(zod@3.24.0)
+ '@opentelemetry/api': 1.9.0
+ jsondiffpatch: 0.6.0
+ zod-to-json-schema: 3.23.5(zod@3.24.0)
+ optionalDependencies:
+ react: 18.3.1
+ zod: 3.24.0
+
ai@4.0.7(react@18.3.1)(zod@3.23.8):
dependencies:
'@ai-sdk/provider': 1.0.1
@@ -15317,9 +15748,9 @@ snapshots:
astring@1.9.0: {}
- astro-expressive-code@0.35.6(astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)):
+ astro-expressive-code@0.35.6(astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)):
dependencies:
- astro: 4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)
+ astro: 4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)
rehype-expressive-code: 0.35.6
astro-icon@1.1.4:
@@ -15331,7 +15762,7 @@ snapshots:
- debug
- supports-color
- astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2):
+ astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2):
dependencies:
'@astrojs/compiler': 2.10.3
'@astrojs/internal-helpers': 0.4.1
@@ -15387,8 +15818,8 @@ snapshots:
tsconfck: 3.1.4(typescript@5.7.2)
unist-util-visit: 5.0.0
vfile: 6.0.3
- vite: 5.4.11(@types/node@22.10.1)(lightningcss@1.28.1)
- vitefu: 1.0.4(vite@5.4.11(@types/node@22.10.1)(lightningcss@1.28.1))
+ vite: 5.4.11(@types/node@22.10.2)(lightningcss@1.28.1)
+ vitefu: 1.0.4(vite@5.4.11(@types/node@22.10.2)(lightningcss@1.28.1))
which-pm: 3.0.0
xxhash-wasm: 1.1.0
yargs-parser: 21.1.1
@@ -16181,7 +16612,7 @@ snapshots:
dotenv@16.4.7: {}
- drizzle-kit@0.24.2:
+ drizzle-kit@0.26.2:
dependencies:
'@drizzle-team/brocli': 0.10.2
'@esbuild-kit/esm-loader': 2.6.5
@@ -16190,7 +16621,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- drizzle-kit@0.26.2:
+ drizzle-kit@0.28.1:
dependencies:
'@drizzle-team/brocli': 0.10.2
'@esbuild-kit/esm-loader': 2.6.5
@@ -16199,7 +16630,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- drizzle-kit@0.28.1:
+ drizzle-kit@0.30.0:
dependencies:
'@drizzle-team/brocli': 0.10.2
'@esbuild-kit/esm-loader': 2.6.5
@@ -16251,6 +16682,23 @@ snapshots:
'@types/react': 18.3.12
react: 18.3.1
+ drizzle-orm@0.36.4(@cloudflare/workers-types@4.20241205.0)(@libsql/client-wasm@0.14.0)(@libsql/client@0.14.0)(@neondatabase/serverless@0.10.4)(@opentelemetry/api@1.9.0)(@types/pg@8.11.10)(@types/react@18.3.12)(react@18.3.1):
+ optionalDependencies:
+ '@cloudflare/workers-types': 4.20241205.0
+ '@libsql/client': 0.14.0
+ '@libsql/client-wasm': 0.14.0
+ '@neondatabase/serverless': 0.10.4
+ '@opentelemetry/api': 1.9.0
+ '@types/pg': 8.11.10
+ '@types/react': 18.3.12
+ react: 18.3.1
+
+ drizzle-seed@0.1.2(drizzle-orm@0.36.4(@cloudflare/workers-types@4.20241205.0)(@libsql/client-wasm@0.14.0)(@libsql/client@0.14.0)(@neondatabase/serverless@0.10.4)(@opentelemetry/api@1.9.0)(@types/pg@8.11.10)(@types/react@18.3.12)(react@18.3.1)):
+ dependencies:
+ pure-rand: 6.1.0
+ optionalDependencies:
+ drizzle-orm: 0.36.4(@cloudflare/workers-types@4.20241205.0)(@libsql/client-wasm@0.14.0)(@libsql/client@0.14.0)(@neondatabase/serverless@0.10.4)(@opentelemetry/api@1.9.0)(@types/pg@8.11.10)(@types/react@18.3.12)(react@18.3.1)
+
drizzle-zod@0.5.1(drizzle-orm@0.33.0(@cloudflare/workers-types@4.20241205.0)(@libsql/client@0.14.0)(@neondatabase/serverless@0.10.4)(@opentelemetry/api@1.9.0)(@types/pg@8.11.10)(@types/react@18.3.12)(react@18.3.1))(zod@3.24.0):
dependencies:
drizzle-orm: 0.33.0(@cloudflare/workers-types@4.20241205.0)(@libsql/client@0.14.0)(@neondatabase/serverless@0.10.4)(@opentelemetry/api@1.9.0)(@types/pg@8.11.10)(@types/react@18.3.12)(react@18.3.1)
@@ -16970,6 +17418,8 @@ snapshots:
globals@11.12.0: {}
+ globals@15.13.0: {}
+
globby@11.1.0:
dependencies:
array-union: 2.1.0
@@ -17276,6 +17726,8 @@ snapshots:
hono@4.6.13: {}
+ hookable@5.5.3: {}
+
html-entities@2.5.2: {}
html-escaper@3.0.3: {}
@@ -17950,6 +18402,10 @@ snapshots:
lru-cache@9.1.2: {}
+ lucide-react@0.468.0(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+
magic-bytes.js@1.10.0: {}
magic-string@0.25.9:
@@ -18883,6 +19339,8 @@ snapshots:
transitivePeerDependencies:
- encoding
+ openapi-types@12.1.3: {}
+
openapi3-ts@4.4.0:
dependencies:
yaml: 2.6.1
@@ -19322,7 +19780,7 @@ snapshots:
'@protobufjs/pool': 1.1.0
'@protobufjs/utf8': 1.1.0
'@types/long': 4.0.2
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
long: 4.0.0
protobufjs@7.4.0:
@@ -19337,7 +19795,7 @@ snapshots:
'@protobufjs/path': 1.1.2
'@protobufjs/pool': 1.1.0
'@protobufjs/utf8': 1.1.0
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
long: 5.2.3
proxy-compare@3.0.1: {}
@@ -19363,6 +19821,8 @@ snapshots:
punycode@2.3.1: {}
+ pure-rand@6.1.0: {}
+
qs@6.11.2:
dependencies:
side-channel: 1.0.6
@@ -19458,6 +19918,8 @@ snapshots:
react-is@18.3.1: {}
+ react-refresh@0.14.2: {}
+
react-remove-scroll-bar@2.3.6(@types/react@18.3.12)(react@18.3.1):
dependencies:
react: 18.3.1
@@ -20102,10 +20564,10 @@ snapshots:
as-table: 1.0.55
get-source: 2.0.12
- starlight-package-managers@0.6.0(@astrojs/starlight@0.28.6(astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)))(astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)):
+ starlight-package-managers@0.6.0(@astrojs/starlight@0.28.6(astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)))(astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)):
dependencies:
- '@astrojs/starlight': 0.28.6(astro@4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))
- astro: 4.16.18(@types/node@22.10.1)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)
+ '@astrojs/starlight': 0.28.6(astro@4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2))
+ astro: 4.16.18(@types/node@22.10.2)(lightningcss@1.28.1)(rollup@4.27.4)(typescript@5.7.2)
state-local@1.0.7: {}
@@ -20484,7 +20946,7 @@ snapshots:
ts-to-zod@3.14.1:
dependencies:
'@oclif/core': 4.0.33
- '@typescript/vfs': 1.6.0(typescript@5.7.2)
+ '@typescript/vfs': 1.6.0(typescript@5.6.2)
case: 1.6.3
chokidar: 3.6.0
fs-extra: 11.2.0
@@ -20496,16 +20958,16 @@ snapshots:
slash: 3.0.0
threads: 1.7.0
tslib: 2.8.1
- tsutils: 3.21.0(typescript@5.7.2)
- typescript: 5.7.2
- zod: 3.23.8
+ tsutils: 3.21.0(typescript@5.6.2)
+ typescript: 5.6.2
+ zod: 3.24.0
transitivePeerDependencies:
- supports-color
ts-to-zod@3.15.0:
dependencies:
'@oclif/core': 4.0.36
- '@typescript/vfs': 1.6.0(typescript@5.7.2)
+ '@typescript/vfs': 1.6.0(typescript@5.6.2)
case: 1.6.3
chokidar: 3.6.0
fs-extra: 11.2.0
@@ -20517,8 +20979,8 @@ snapshots:
slash: 3.0.0
threads: 1.7.0
tslib: 2.8.1
- tsutils: 3.21.0(typescript@5.7.2)
- typescript: 5.7.2
+ tsutils: 3.21.0(typescript@5.6.2)
+ typescript: 5.6.2
zod: 3.24.0
transitivePeerDependencies:
- supports-color
@@ -20568,10 +21030,10 @@ snapshots:
- tsx
- yaml
- tsutils@3.21.0(typescript@5.7.2):
+ tsutils@3.21.0(typescript@5.6.2):
dependencies:
tslib: 1.14.1
- typescript: 5.7.2
+ typescript: 5.6.2
tsx@4.19.2:
dependencies:
@@ -20821,6 +21283,24 @@ snapshots:
- supports-color
- terser
+ vite-node@1.6.0(@types/node@22.10.2)(lightningcss@1.28.1):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.0(supports-color@8.1.1)
+ pathe: 1.1.2
+ picocolors: 1.1.1
+ vite: 5.4.11(@types/node@22.10.2)(lightningcss@1.28.1)
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
vite-node@2.1.6(@types/node@22.10.0)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1):
dependencies:
cac: 6.7.14
@@ -20842,13 +21322,13 @@ snapshots:
- tsx
- yaml
- vite-node@2.1.6(@types/node@22.10.1)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1):
+ vite-node@2.1.6(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1):
dependencies:
cac: 6.7.14
debug: 4.4.0(supports-color@8.1.1)
es-module-lexer: 1.5.4
pathe: 1.1.2
- vite: 6.0.1(@types/node@22.10.1)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
+ vite: 6.0.1(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -20895,6 +21375,16 @@ snapshots:
fsevents: 2.3.3
lightningcss: 1.28.1
+ vite@5.4.11(@types/node@22.10.2)(lightningcss@1.28.1):
+ dependencies:
+ esbuild: 0.21.5
+ postcss: 8.4.49
+ rollup: 4.28.1
+ optionalDependencies:
+ '@types/node': 22.10.2
+ fsevents: 2.3.3
+ lightningcss: 1.28.1
+
vite@6.0.1(@types/node@22.10.0)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1):
dependencies:
esbuild: 0.24.0
@@ -20908,22 +21398,22 @@ snapshots:
tsx: 4.19.2
yaml: 2.6.1
- vite@6.0.1(@types/node@22.10.1)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1):
+ vite@6.0.1(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1):
dependencies:
esbuild: 0.24.0
postcss: 8.4.49
rollup: 4.27.4
optionalDependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
fsevents: 2.3.3
jiti: 1.21.6
lightningcss: 1.28.1
tsx: 4.19.2
yaml: 2.6.1
- vitefu@1.0.4(vite@5.4.11(@types/node@22.10.1)(lightningcss@1.28.1)):
+ vitefu@1.0.4(vite@5.4.11(@types/node@22.10.2)(lightningcss@1.28.1)):
optionalDependencies:
- vite: 5.4.11(@types/node@22.10.1)(lightningcss@1.28.1)
+ vite: 5.4.11(@types/node@22.10.2)(lightningcss@1.28.1)
vitest@1.6.0(@types/node@22.10.1)(lightningcss@1.28.1):
dependencies:
@@ -20959,6 +21449,40 @@ snapshots:
- supports-color
- terser
+ vitest@1.6.0(@types/node@22.10.2)(lightningcss@1.28.1):
+ dependencies:
+ '@vitest/expect': 1.6.0
+ '@vitest/runner': 1.6.0
+ '@vitest/snapshot': 1.6.0
+ '@vitest/spy': 1.6.0
+ '@vitest/utils': 1.6.0
+ acorn-walk: 8.3.4
+ chai: 4.5.0
+ debug: 4.4.0(supports-color@8.1.1)
+ execa: 8.0.1
+ local-pkg: 0.5.1
+ magic-string: 0.30.15
+ pathe: 1.1.2
+ picocolors: 1.1.1
+ std-env: 3.8.0
+ strip-literal: 2.1.1
+ tinybench: 2.9.0
+ tinypool: 0.8.4
+ vite: 5.4.11(@types/node@22.10.2)(lightningcss@1.28.1)
+ vite-node: 1.6.0(@types/node@22.10.2)(lightningcss@1.28.1)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/node': 22.10.2
+ transitivePeerDependencies:
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
vitest@2.1.6(@types/node@22.10.0)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1):
dependencies:
'@vitest/expect': 2.1.6
@@ -20997,10 +21521,10 @@ snapshots:
- tsx
- yaml
- vitest@2.1.6(@types/node@22.10.1)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1):
+ vitest@2.1.6(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1):
dependencies:
'@vitest/expect': 2.1.6
- '@vitest/mocker': 2.1.6(vite@6.0.1(@types/node@22.10.1)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1))
+ '@vitest/mocker': 2.1.6(vite@6.0.1(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1))
'@vitest/pretty-format': 2.1.6
'@vitest/runner': 2.1.6
'@vitest/snapshot': 2.1.6
@@ -21016,11 +21540,11 @@ snapshots:
tinyexec: 0.3.1
tinypool: 1.0.2
tinyrainbow: 1.2.0
- vite: 6.0.1(@types/node@22.10.1)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
- vite-node: 2.1.6(@types/node@22.10.1)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
+ vite: 6.0.1(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
+ vite-node: 2.1.6(@types/node@22.10.2)(jiti@1.21.6)(lightningcss@1.28.1)(tsx@4.19.2)(yaml@2.6.1)
why-is-node-running: 2.3.0
optionalDependencies:
- '@types/node': 22.10.1
+ '@types/node': 22.10.2
transitivePeerDependencies:
- jiti
- less
@@ -21375,6 +21899,34 @@ snapshots:
- supports-color
- utf-8-validate
+ wrangler@3.95.0(@cloudflare/workers-types@4.20241205.0):
+ dependencies:
+ '@cloudflare/kv-asset-handler': 0.3.4
+ '@cloudflare/workers-shared': 0.11.0
+ '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19)
+ '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19)
+ blake3-wasm: 2.1.5
+ chokidar: 4.0.1
+ date-fns: 4.1.0
+ esbuild: 0.17.19
+ itty-time: 1.0.6
+ miniflare: 3.20241205.0
+ nanoid: 3.3.8
+ path-to-regexp: 6.3.0
+ resolve: 1.22.8
+ selfsigned: 2.4.1
+ source-map: 0.6.1
+ unenv: unenv-nightly@2.0.0-20241204-140205-a5d5190
+ workerd: 1.20241205.0
+ xxhash-wasm: 1.1.0
+ optionalDependencies:
+ '@cloudflare/workers-types': 4.20241205.0
+ fsevents: 2.3.3
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
wrap-ansi@6.2.0:
dependencies:
ansi-styles: 4.3.0
@@ -21478,6 +22030,8 @@ snapshots:
mustache: 4.2.0
stacktracey: 2.1.8
+ zhead@2.2.4: {}
+
zod-package-json@1.0.3:
dependencies:
zod: 3.24.0
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index b3de4a6fe..1ae0f7187 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -3,6 +3,7 @@ packages:
- "api"
- "fp-services"
- "honc-code-gen"
+ - "lilo/*"
- "packages/*"
- "examples/*"
- "examples/service-bindings/*"