···4# paths because the flake.nix is written in a way such that top-level members
5# (`weaver-cli` and `weaver-server`) are built as different derivations which avoid being
6# rebuilt if the other package's sources change.
7-members = ["crates/*", "crates/weaver-server"]
89#default-members = ["crates/weaver-cli"]
10···39markdown-weaver = { git = "https://github.com/rsform/markdown-weaver" }
40markdown-weaver-escape = { git = "https://github.com/rsform/markdown-weaver" }
4142-jacquard = { git = "https://tangled.org/@nonbinary.computer/jacquard", default-features = false, features = ["derive", "api_bluesky", "dns"] }
43jacquard-api = { git = "https://tangled.org/@nonbinary.computer/jacquard" }
44jacquard-axum = { git = "https://tangled.org/@nonbinary.computer/jacquard" }
45-tree_magic = { version = "0.2.3", features = ["cli"] }
4647[profile]
48
···4# paths because the flake.nix is written in a way such that top-level members
5# (`weaver-cli` and `weaver-server`) are built as different derivations which avoid being
6# rebuilt if the other package's sources change.
7+members = ["crates/*", "crates/weaver-server", "crates/weaver-server"]
89#default-members = ["crates/weaver-cli"]
10···39markdown-weaver = { git = "https://github.com/rsform/markdown-weaver" }
40markdown-weaver-escape = { git = "https://github.com/rsform/markdown-weaver" }
4142+jacquard = { git = "https://tangled.org/@nonbinary.computer/jacquard", default-features = false, features = ["derive", "api_bluesky"] }
43jacquard-api = { git = "https://tangled.org/@nonbinary.computer/jacquard" }
44jacquard-axum = { git = "https://tangled.org/@nonbinary.computer/jacquard" }
04546[profile]
47
···25pub mod base_html;
26pub mod code_pretty;
27pub mod css;
028pub mod static_site;
29pub mod theme;
30pub mod types;
31pub mod utils;
032pub mod walker;
3334pub static OBSIDIAN_NOTE_LINK_RE: LazyLock<Regex> = LazyLock::new(|| {
···25pub mod base_html;
26pub mod code_pretty;
27pub mod css;
28+#[cfg(not(target_family = "wasm"))]
29pub mod static_site;
30pub mod theme;
31pub mod types;
32pub mod utils;
33+#[cfg(not(target_family = "wasm"))]
34pub mod walker;
3536pub static OBSIDIAN_NOTE_LINK_RE: LazyLock<Regex> = LazyLock::new(|| {
···7# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
89[dependencies]
10-dioxus = { version = "0.6.0", features = ["router", "fullstack"] }
011weaver-common = { path = "../weaver-common" }
12-weaver-workspace-hack = { version = "0.1", path = "../weaver-workspace-hack" }
13-14-jacquard = { workspace = true, features = ["tracing"] }
00001516[features]
17default = ["web"]
···21desktop = ["dioxus/desktop"]
22# The feature that are only required for the mobile = ["dioxus/mobile"] build target should be optional and only enabled in the mobile = ["dioxus/mobile"] feature
23mobile = ["dioxus/mobile"]
00
···7# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
89[dependencies]
10+dashmap = "6.1.0"
11+dioxus = { version = "0.7.0", features = ["router", "fullstack"] }
12weaver-common = { path = "../weaver-common" }
13+jacquard = { workspace = true, features = ["streaming"] }
14+jacquard-axum = { workspace = true, optional = true }
15+weaver-api = { path = "../weaver-api", features = ["streaming"] }
16+markdown-weaver = { workspace = true }
17+moka = { version = "0.12", features = ["future"], optional = true }
18+mini-moka = { version = "0.10" }
19+dioxus-primitives = { git = "https://github.com/DioxusLabs/components", version = "0.0.1", default-features = false }
2021[features]
22default = ["web"]
···26desktop = ["dioxus/desktop"]
27# The feature that are only required for the mobile = ["dioxus/mobile"] build target should be optional and only enabled in the mobile = ["dioxus/mobile"] feature
28mobile = ["dioxus/mobile"]
29+# The feature that are only required for the server = ["dioxus/server"] build target should be optional and only enabled in the server = ["dioxus/server"] feature
30+server = ["dioxus/server", "dep:jacquard-axum", "dep:moka"]
···1-await-holding-invalid-types = [
2- "generational_box::GenerationalRef",
3- { path = "generational_box::GenerationalRef", reason = "Reads should not be held over an await point. This will cause any writes to fail while the await is pending since the read borrow is still active." },
4- "generational_box::GenerationalRefMut",
5- { path = "generational_box::GenerationalRefMut", reason = "Write should not be held over an await point. This will cause any reads or writes to fail while the await is pending since the write borrow is still active." },
6- "dioxus_signals::Write",
7- { path = "dioxus_signals::Write", reason = "Write should not be held over an await point. This will cause any reads or writes to fail while the await is pending since the write borrow is still active." },
8-]
···1-use dioxus::prelude::*;
2-3-const ECHO_CSS: Asset = asset!("/assets/styling/echo.css");
4-5-/// Echo component that demonstrates fullstack server functions.
6-#[component]
7-pub fn Echo() -> Element {
8- // use_signal is a hook. Hooks in dioxus must be run in a consistent order every time the component is rendered.
9- // That means they can't be run inside other hooks, async blocks, if statements, or loops.
10- //
11- // use_signal is a hook that creates a state for the component. It takes a closure that returns the initial value of the state.
12- // The state is automatically tracked and will rerun any other hooks or components that read it whenever it changes.
13- let mut response = use_signal(|| String::new());
14-15- rsx! {
16- document::Link { rel: "stylesheet", href: ECHO_CSS }
17-18- div {
19- id: "echo",
20- h4 { "ServerFn Echo" }
21- input {
22- placeholder: "Type here to echo...",
23- // `oninput` is an event handler that will run when the input changes. It can return either nothing or a future
24- // that will be run when the event runs.
25- oninput: move |event| async move {
26- // When we call the echo_server function from the client, it will fire a request to the server and return
27- // the response. It handles serialization and deserialization of the request and response for us.
28- let data = echo_server(event.value()).await.unwrap();
29-30- // After we have the data from the server, we can set the state of the signal to the new value.
31- // Since we read the `response` signal later in this component, the component will rerun.
32- response.set(data);
33- },
34- }
35-36- // Signals can be called like a function to clone the current value of the signal
37- if !response().is_empty() {
38- p {
39- "Server echoed: "
40- // Since we read the signal inside this component, the component "subscribes" to the signal. Whenever
41- // the signal changes, the component will rerun.
42- i { "{response}" }
43- }
44- }
45- }
46- }
47-}
48-49-// Server functions let us define public APIs on the server that can be called like a normal async function from the client.
50-// Each server function needs to be annotated with the `#[server]` attribute, accept and return serializable types, and return
51-// a `Result` with the error type [`ServerFnError`].
52-//
53-// When the server function is called from the client, it will just serialize the arguments, call the API, and deserialize the
54-// response.
55-#[server]
56-async fn echo_server(input: String) -> Result<String, ServerFnError> {
57- // The body of server function like this comment are only included on the server. If you have any server-only logic like
58- // database queries, you can put it here. Any imports for the server function should either be imported inside the function
59- // or imported under a `#[cfg(feature = "server")]` block.
60- Ok(input)
61-}
···1-use dioxus::prelude::*;
2-3-const HEADER_SVG: Asset = asset!("/assets/header.svg");
4-5-#[component]
6-pub fn Hero() -> Element {
7- rsx! {
8- // We can create elements inside the rsx macro with the element name followed by a block of attributes and children.
9- div {
10- // Attributes should be defined in the element before any children
11- id: "hero",
12- // After all attributes are defined, we can define child elements and components
13- img { src: HEADER_SVG, id: "header" }
14- div { id: "links",
15- // The RSX macro also supports text nodes surrounded by quotes
16- a { href: "https://dioxuslabs.com/learn/0.6/", "📚 Learn Dioxus" }
17- a { href: "https://dioxuslabs.com/awesome", "🚀 Awesome Dioxus" }
18- a { href: "https://github.com/dioxus-community/", "📡 Community Libraries" }
19- a { href: "https://github.com/DioxusLabs/sdk", "⚙️ Dioxus Development Kit" }
20- a { href: "https://marketplace.visualstudio.com/items?itemName=DioxusLabs.dioxus", "💫 VSCode Extension" }
21- a { href: "https://discord.gg/XgGxMSkvUM", "👋 Community Discord" }
22- }
23- }
24- }
25-}
···0000000000000000000000000
+41
crates/weaver-server/src/components/identity.rs
···00000000000000000000000000000000000000000
···1+use crate::{fetch, Route};
2+use dioxus::prelude::*;
3+use jacquard::{
4+ client::BasicClient,
5+ types::{ident::AtIdentifier, tid::Tid},
6+ CowStr,
7+};
8+use weaver_api::sh_weaver::notebook::NotebookView;
9+#[component]
10+pub fn Repository(ident: AtIdentifier<'static>) -> Element {
11+ rsx! {
12+ // We can create elements inside the rsx macro with the element name followed by a block of attributes and children.
13+ div {
14+ Outlet::<Route> {}
15+ }
16+ }
17+}
18+19+#[component]
20+pub fn RepositoryIndex(ident: AtIdentifier<'static>) -> Element {
21+ let fetcher = use_context::<fetch::CachedFetcher>();
22+ let notebooks = use_signal(|| fetcher.list_recent_notebooks());
23+ rsx! {
24+ for notebook in notebooks.iter() {
25+ {
26+ let view = ¬ebook.0;
27+ rsx! {
28+ div {
29+ key: "{view.cid}",
30+ NotebookCard { notebook: view.clone() }
31+ }
32+ }
33+ }
34+ }
35+ }
36+}
37+38+#[component]
39+pub fn NotebookCard(notebook: NotebookView<'static>) -> Element {
40+ rsx! {}
41+}
+7-4
crates/weaver-server/src/components/mod.rs
···2//! They can be used to defined common UI elements like buttons, forms, and modals. In this template, we define a Hero
3//! component and an Echo component for fullstack apps to be used in our app.
45-mod hero;
6-pub use hero::Hero;
0078-mod echo;
9-pub use echo::Echo;
0
···2//! They can be used to defined common UI elements like buttons, forms, and modals. In this template, we define a Hero
3//! component and an Echo component for fullstack apps to be used in our app.
45+mod cssblob;
6+7+mod entry;
8+pub use entry::{Entry, EntryCard};
910+mod identity;
11+pub use identity::{Repository, RepositoryIndex};
12+pub mod avatar;
···1// The dioxus prelude contains a ton of common items used in dioxus apps. It's a good idea to import wherever you
2// need dioxus
3-use dioxus::prelude::*;
4-5-use views::{Blog, Home, Navbar};
000067/// Define a components module that contains all shared components for our app.
8mod components;
09/// Define a views module that contains the UI for all Layouts and Routes for our app.
10mod views;
1112/// The Route enum is used to define the structure of internal routes in our app. All route enums need to derive
13/// the [`Routable`] trait, which provides the necessary methods for the router to work.
14-///
15/// Each variant represents a different URL pattern that can be matched by the router. If that pattern is matched,
16/// the components for that route will be rendered.
17#[derive(Debug, Clone, Routable, PartialEq)]
···24 // the component for that route will be rendered. The component name that is rendered defaults to the variant name.
25 #[route("/")]
26 Home {},
27- // The route attribute can include dynamic parameters that implement [`std::str::FromStr`] and [`std::fmt::Display`] with the `:` syntax.
28- // In this case, id will match any integer like `/blog/123` or `/blog/-456`.
29- #[route("/blog/:id")]
30- // Fields of the route variant will be passed to the component as props. In this case, the blog component must accept
31- // an `id` prop of type `i32`.
32- Blog { id: i32 },
00000033}
3435// We can import assets in dioxus with the `asset!` macro. This macro takes a path to an asset relative to the crate root.
···39const MAIN_CSS: Asset = asset!("/assets/styling/main.css");
4041fn main() {
42- // The `launch` function is the main entry point for a dioxus app. It takes a component and renders it with the platform feature
43- // you have enabled
00000000000044 dioxus::launch(App);
45}
46···51#[component]
52fn App() -> Element {
53 // The `rsx!` macro lets us define HTML inside of rust. It expands to an Element with all of our HTML inside.
054 rsx! {
55 // In addition to element and text (which we will see later), rsx can contain other components. In this case,
56 // we are using the `document::Link` component to add a link to our favicon and main CSS file into the head of our app.
···63 Router::<Route> {}
64 }
65}
000000000000000000000
···1// The dioxus prelude contains a ton of common items used in dioxus apps. It's a good idea to import wherever you
2// need dioxus
3+use components::{Entry, Repository, RepositoryIndex};
4+use dioxus::{fullstack::FullstackContext, prelude::*};
5+use jacquard::{
6+ client::BasicClient, smol_str::SmolStr, types::did::Did, types::string::AtIdentifier, CowStr,
7+};
8+use std::sync::Arc;
9+use views::{Home, Navbar, Notebook, NotebookIndex, NotebookPage};
1011/// Define a components module that contains all shared components for our app.
12mod components;
13+mod fetch;
14/// Define a views module that contains the UI for all Layouts and Routes for our app.
15mod views;
1617/// The Route enum is used to define the structure of internal routes in our app. All route enums need to derive
18/// the [`Routable`] trait, which provides the necessary methods for the router to work.
19+///
20/// Each variant represents a different URL pattern that can be matched by the router. If that pattern is matched,
21/// the components for that route will be rendered.
22#[derive(Debug, Clone, Routable, PartialEq)]
···29 // the component for that route will be rendered. The component name that is rendered defaults to the variant name.
30 #[route("/")]
31 Home {},
32+ #[layout(ErrorLayout)]
33+ #[nest("/:ident")]
34+ #[layout(components::Repository)]
35+ #[route("/")]
36+ RepositoryIndex { ident: AtIdentifier<'static> },
37+ #[nest("/:book_title")]
38+ #[layout(views::Notebook)]
39+ #[route("/")]
40+ NotebookIndex { ident: AtIdentifier<'static>, book_title: SmolStr },
41+ #[route("/:title")]
42+ Entry { ident: AtIdentifier<'static>, book_title: SmolStr, title: SmolStr }
43+44}
4546// We can import assets in dioxus with the `asset!` macro. This macro takes a path to an asset relative to the crate root.
···50const MAIN_CSS: Asset = asset!("/assets/styling/main.css");
5152fn main() {
53+ // Run `serve()` on the server only
54+ #[cfg(feature = "server")]
55+ dioxus::serve(|| async move {
56+ // Create a new router for our app using the `router` function
57+ let mut router = dioxus::server::router(App);
58+59+ // .. customize the router, adding layers and new routes
60+61+ // And then return the router
62+ Ok(router)
63+ });
64+65+ // When not on the server, just run `launch()` like normal
66+ #[cfg(not(feature = "server"))]
67 dioxus::launch(App);
68}
69···74#[component]
75fn App() -> Element {
76 // The `rsx!` macro lets us define HTML inside of rust. It expands to an Element with all of our HTML inside.
77+ use_context_provider(|| fetch::CachedFetcher::new(Arc::new(BasicClient::unauthenticated())));
78 rsx! {
79 // In addition to element and text (which we will see later), rsx can contain other components. In this case,
80 // we are using the `document::Link` component to add a link to our favicon and main CSS file into the head of our app.
···87 Router::<Route> {}
88 }
89}
90+91+// And then our Outlet is wrapped in a fallback UI
92+#[component]
93+fn ErrorLayout() -> Element {
94+ rsx! {
95+ ErrorBoundary {
96+ handle_error: move |err: ErrorContext| {
97+ let http_error = FullstackContext::commit_error_status(err.error().unwrap());
98+ match http_error.status {
99+ StatusCode::NOT_FOUND => rsx! { div { "404 - Page not found" } },
100+ _ => rsx! { div { "An unknown error occurred" } },
101+ }
102+ },
103+ Outlet::<Route> {}
104+ }
105+ }
106+}
107+108+struct Config {
109+ did: Option<Did<'static>>,
110+}
-39
crates/weaver-server/src/views/blog.rs
···1-use crate::Route;
2-use dioxus::prelude::*;
3-4-const BLOG_CSS: Asset = asset!("/assets/styling/blog.css");
5-6-/// The Blog page component that will be rendered when the current route is `[Route::Blog]`
7-///
8-/// The component takes a `id` prop of type `i32` from the route enum. Whenever the id changes, the component function will be
9-/// re-run and the rendered HTML will be updated.
10-#[component]
11-pub fn Blog(id: i32) -> Element {
12- rsx! {
13- document::Link { rel: "stylesheet", href: BLOG_CSS }
14-15- div {
16- id: "blog",
17-18- // Content
19- h1 { "This is blog #{id}!" }
20- p { "In blog #{id}, we show how the Dioxus router works and how URL parameters can be passed as props to our route components." }
21-22- // Navigation links
23- // The `Link` component lets us link to other routes inside our app. It takes a `to` prop of type `Route` and
24- // any number of child nodes.
25- Link {
26- // The `to` prop is the route that the link should navigate to. We can use the `Route` enum to link to the
27- // blog page with the id of -1. Since we are using an enum instead of a string, all of the routes will be checked
28- // at compile time to make sure they are valid.
29- to: Route::Blog { id: id - 1 },
30- "Previous"
31- }
32- span { " <---> " }
33- Link {
34- to: Route::Blog { id: id + 1 },
35- "Next"
36- }
37- }
38- }
39-}
···000000000000000000000000000000000000000
+14-3
crates/weaver-server/src/views/home.rs
···1-use crate::components::{Echo, Hero};
2use dioxus::prelude::*;
34/// The Home page component that will be rendered when the current route is `[Route::Home]`
5#[component]
6pub fn Home() -> Element {
007 rsx! {
8- Hero {}
9- Echo {}
00000000010 }
11}
···1+use crate::{components::EntryCard, fetch};
2use dioxus::prelude::*;
34/// The Home page component that will be rendered when the current route is `[Route::Home]`
5#[component]
6pub fn Home() -> Element {
7+ let fetcher = use_context::<fetch::CachedFetcher>();
8+ let entries = use_signal(|| fetcher.list_recent_entries());
9 rsx! {
10+ for entry in entries.iter() {
11+ {
12+ let view = &entry.0;
13+ rsx! {
14+ div {
15+ key: "{view.entry.cid}",
16+ EntryCard { entry: view.clone() }
17+ }
18+ }
19+ }
20+ }
21 }
22}
+6-3
crates/weaver-server/src/views/mod.rs
···11mod home;
12pub use home::Home;
1314-mod blog;
15-pub use blog::Blog;
16-17mod navbar;
18pub use navbar::Navbar;
000000
···11mod home;
12pub use home::Home;
1300014mod navbar;
15pub use navbar::Navbar;
16+17+mod notebookpage;
18+pub use notebookpage::NotebookPage;
19+20+mod notebook;
21+pub use notebook::{Notebook, NotebookIndex};
+1-4
crates/weaver-server/src/views/navbar.rs
···19 to: Route::Home {},
20 "Home"
21 }
22- Link {
23- to: Route::Blog { id: 1 },
24- "Blog"
25- }
26 }
2728 // The `Outlet` component is used to render the next component inside the layout. In this case, it will render either
···19 to: Route::Home {},
20 "Home"
21 }
22+00023 }
2425 // The `Outlet` component is used to render the next component inside the layout. In this case, it will render either
+30
crates/weaver-server/src/views/notebook.rs
···000000000000000000000000000000
···1+use crate::{fetch, Route};
2+use dioxus::prelude::*;
3+use jacquard::{
4+ client::BasicClient,
5+ smol_str::SmolStr,
6+ types::{ident::AtIdentifier, tid::Tid},
7+ CowStr,
8+};
9+use std::sync::Arc;
10+11+const BLOG_CSS: Asset = asset!("/assets/styling/blog.css");
12+13+/// The Blog page component that will be rendered when the current route is `[Route::Blog]`
14+///
15+/// The component takes a `id` prop of type `i32` from the route enum. Whenever the id changes, the component function will be
16+/// re-run and the rendered HTML will be updated.
17+#[component]
18+pub fn Notebook(ident: AtIdentifier<'static>, book_title: SmolStr) -> Element {
19+ let fetcher = use_context::<fetch::CachedFetcher>();
20+ rsx! {
21+ document::Link { rel: "stylesheet", href: BLOG_CSS }
22+ Outlet::<Route> {}
23+ }
24+}
25+26+#[component]
27+pub fn NotebookIndex(ident: AtIdentifier<'static>, book_title: SmolStr) -> Element {
28+ let fetcher = use_context::<fetch::CachedFetcher>();
29+ rsx! {}
30+}
+25
crates/weaver-server/src/views/notebookpage.rs
···0000000000000000000000000
···1+use crate::Route;
2+use dioxus::prelude::*;
3+use jacquard::types::tid::Tid;
4+5+const BLOG_CSS: Asset = asset!("/assets/styling/blog.css");
6+7+/// The Blog page component that will be rendered when the current route is `[Route::Blog]`
8+///
9+/// The component takes a `id` prop of type `i32` from the route enum. Whenever the id changes, the component function will be
10+/// re-run and the rendered HTML will be updated.
11+#[component]
12+pub fn NotebookPage(id: Tid, children: Element) -> Element {
13+ rsx! {
14+ document::Link { rel: "stylesheet", href: BLOG_CSS }
15+16+ div {
17+ id: "blog",
18+19+ // Content
20+ h1 { "This is blog #{id}!" }
21+ p { "In blog #{id}, we show how the Dioxus router works and how URL parameters can be passed as props to our route components." }
22+23+ }
24+ }
25+}
-4
crates/weaver-workspace-hack/.gitattributes
···1-# Avoid putting conflict markers in the generated Cargo.toml file, since their presence breaks
2-# Cargo.
3-# Also do not check out the file as CRLF on Windows, as that's what hakari needs.
4-Cargo.toml merge=binary -crlf
···0000
-110
crates/weaver-workspace-hack/Cargo.toml
···1-# This file is generated by `cargo hakari`.
2-# To regenerate, run:
3-# cargo hakari generate
4-5-[package]
6-name = "weaver-workspace-hack"
7-version = "0.1.0"
8-description = "workspace-hack package, managed by hakari"
9-license.workspace = true
10-edition.workspace = true
11-# You can choose to publish this crate: see https://docs.rs/cargo-hakari/latest/cargo_hakari/publishing.
12-publish = false
13-14-# The parts of the file between the BEGIN HAKARI SECTION and END HAKARI SECTION comments
15-# are managed by hakari.
16-17-### BEGIN HAKARI SECTION
18-[dependencies]
19-aho-corasick = { version = "1" }
20-byteorder = { version = "1" }
21-bytes = { version = "1", features = ["serde"] }
22-data-encoding = { version = "2" }
23-diesel = { version = "2", features = ["chrono", "i-implement-a-third-party-backend-and-opt-into-breaking-changes", "postgres", "serde_json", "sqlite"] }
24-diesel-async = { version = "0.5", features = ["deadpool", "postgres", "sync-connection-wrapper"] }
25-elliptic-curve = { version = "0.13", features = ["digest", "hazmat", "jwk", "pem", "std"] }
26-futures-channel = { version = "0.3", features = ["sink"] }
27-futures-core = { version = "0.3" }
28-futures-task = { version = "0.3", default-features = false, features = ["std"] }
29-futures-util = { version = "0.3", features = ["channel", "io", "sink"] }
30-generic-array = { version = "0.14", default-features = false, features = ["more_lengths", "serde", "zeroize"] }
31-hashbrown = { version = "0.15", features = ["serde"] }
32-idna = { version = "1" }
33-jacquard = { git = "https://tangled.org/@nonbinary.computer/jacquard", default-features = false, features = ["api_bluesky", "derive", "dns", "loopback", "tracing", "websocket", "zstd"] }
34-jacquard-api = { git = "https://tangled.org/@nonbinary.computer/jacquard", features = ["bluesky", "sh_weaver"] }
35-jacquard-common = { git = "https://tangled.org/@nonbinary.computer/jacquard", features = ["tracing", "websocket", "zstd"] }
36-jacquard-identity = { git = "https://tangled.org/@nonbinary.computer/jacquard", default-features = false, features = ["cache", "dns", "tracing"] }
37-jacquard-lexicon = { git = "https://tangled.org/@nonbinary.computer/jacquard" }
38-jacquard-oauth = { git = "https://tangled.org/@nonbinary.computer/jacquard", features = ["browser-open", "loopback", "tracing"] }
39-log = { version = "0.4", default-features = false, features = ["std"] }
40-memchr = { version = "2" }
41-miette = { version = "7", features = ["fancy", "syntect-highlighter"] }
42-minijinja = { version = "2" }
43-minimal-lexical = { version = "0.2", default-features = false, features = ["std"] }
44-nom = { version = "7" }
45-num-traits = { version = "0.2", default-features = false, features = ["i128", "libm", "std"] }
46-p384 = { version = "0.13", default-features = false, features = ["ecdsa"] }
47-percent-encoding = { version = "2" }
48-rand = { version = "0.8", features = ["small_rng"] }
49-regex-automata = { version = "0.4", default-features = false, features = ["dfa", "hybrid", "meta", "nfa", "perf", "std", "unicode"] }
50-reqwest = { version = "0.12", features = ["gzip", "json", "rustls-tls", "stream"] }
51-sec1 = { version = "0.7", features = ["pem", "serde", "std", "subtle"] }
52-serde_json = { version = "1", features = ["alloc", "preserve_order", "raw_value"] }
53-sha2 = { version = "0.10", features = ["oid"] }
54-smallvec = { version = "1", default-features = false, features = ["const_new"] }
55-subtle = { version = "2" }
56-syn = { version = "2", features = ["extra-traits", "fold", "full", "visit", "visit-mut"] }
57-syntect = { version = "5", features = ["default-fancy"] }
58-time = { version = "0.3", features = ["formatting", "macros", "parsing"] }
59-tokio = { version = "1", features = ["full"] }
60-tokio-util = { version = "0.7", features = ["codec", "io"] }
61-toml = { version = "0.8", features = ["preserve_order"] }
62-tower-http = { version = "0.6", features = ["cors", "fs", "normalize-path", "request-id", "timeout", "trace"] }
63-tracing = { version = "0.1", features = ["log"] }
64-tracing-core = { version = "0.1" }
65-uuid = { version = "1", features = ["serde", "v4", "v7"] }
66-winnow = { version = "0.7" }
67-zerocopy = { version = "0.8", default-features = false, features = ["derive", "simd"] }
68-zeroize = { version = "1", features = ["derive", "serde"] }
69-70-[build-dependencies]
71-aho-corasick = { version = "1" }
72-bytes = { version = "1", features = ["serde"] }
73-data-encoding = { version = "2" }
74-diesel_derives = { version = "2", features = ["32-column-tables", "chrono", "postgres", "sqlite", "with-deprecated"] }
75-elliptic-curve = { version = "0.13", features = ["digest", "hazmat", "jwk", "pem", "std"] }
76-futures-channel = { version = "0.3", features = ["sink"] }
77-futures-core = { version = "0.3" }
78-futures-task = { version = "0.3", default-features = false, features = ["std"] }
79-futures-util = { version = "0.3", features = ["channel", "io", "sink"] }
80-generic-array = { version = "0.14", default-features = false, features = ["more_lengths", "serde", "zeroize"] }
81-idna = { version = "1" }
82-jacquard-common = { git = "https://tangled.org/@nonbinary.computer/jacquard", features = ["tracing", "websocket", "zstd"] }
83-jacquard-lexicon = { git = "https://tangled.org/@nonbinary.computer/jacquard" }
84-log = { version = "0.4", default-features = false, features = ["std"] }
85-memchr = { version = "2" }
86-miette = { version = "7", features = ["fancy", "syntect-highlighter"] }
87-minimal-lexical = { version = "0.2", default-features = false, features = ["std"] }
88-nom = { version = "7" }
89-num-traits = { version = "0.2", default-features = false, features = ["i128", "libm", "std"] }
90-percent-encoding = { version = "2" }
91-rand = { version = "0.8", features = ["small_rng"] }
92-regex-automata = { version = "0.4", default-features = false, features = ["dfa", "hybrid", "meta", "nfa", "perf", "std", "unicode"] }
93-reqwest = { version = "0.12", features = ["gzip", "json", "rustls-tls", "stream"] }
94-sec1 = { version = "0.7", features = ["pem", "serde", "std", "subtle"] }
95-serde_json = { version = "1", features = ["alloc", "preserve_order", "raw_value"] }
96-sha2 = { version = "0.10", features = ["oid"] }
97-smallvec = { version = "1", default-features = false, features = ["const_new"] }
98-subtle = { version = "2" }
99-syn = { version = "2", features = ["extra-traits", "fold", "full", "visit", "visit-mut"] }
100-syntect = { version = "5", features = ["default-fancy"] }
101-time = { version = "0.3", features = ["formatting", "macros", "parsing"] }
102-tokio = { version = "1", features = ["full"] }
103-tokio-util = { version = "0.7", features = ["codec", "io"] }
104-tracing = { version = "0.1", features = ["log"] }
105-tracing-core = { version = "0.1" }
106-winnow = { version = "0.7" }
107-zerocopy = { version = "0.8", default-features = false, features = ["derive", "simd"] }
108-zeroize = { version = "1", features = ["derive", "serde"] }
109-110-### END HAKARI SECTION