From 1d948e149c8111a2fe185fd56daa269f184b336e Mon Sep 17 00:00:00 2001
From: Elaina <48662592+oestradiol@users.noreply.github.com>
Date: Thu, 12 Sep 2024 03:34:35 -0300
Subject: [PATCH 1/7] Preparing for Draft Pull Request
---
Cargo.lock | 412 +++++++++++++++++-
Cargo.toml | 13 +
atrium-xrpc-wss-client/.gitignore | 2 +
atrium-xrpc-wss-client/CHANGELOG.md | 5 +
atrium-xrpc-wss-client/Cargo.toml | 27 ++
atrium-xrpc-wss-client/README.md | 1 +
atrium-xrpc-wss-client/src/client.rs | 87 ++++
atrium-xrpc-wss-client/src/lib.rs | 6 +
.../src/subscriptions/mod.rs | 1 +
.../subscriptions/repositories/firehose.rs | 225 ++++++++++
.../src/subscriptions/repositories/mod.rs | 107 +++++
.../subscriptions/repositories/type_defs.rs | 54 +++
atrium-xrpc-wss/.gitignore | 2 +
atrium-xrpc-wss/CHANGELOG.md | 5 +
atrium-xrpc-wss/Cargo.toml | 21 +
atrium-xrpc-wss/README.md | 1 +
atrium-xrpc-wss/src/client/mod.rs | 27 ++
atrium-xrpc-wss/src/client/xprc_uri.rs | 16 +
atrium-xrpc-wss/src/lib.rs | 4 +
.../src/subscriptions/frames/mod.rs | 86 ++++
.../src/subscriptions/frames/tests.rs | 61 +++
.../src/subscriptions/handlers/mod.rs | 3 +
.../subscriptions/handlers/repositories.rs | 125 ++++++
atrium-xrpc-wss/src/subscriptions/mod.rs | 81 ++++
examples/firehose/Cargo.toml | 11 +-
examples/firehose/src/lib.rs | 2 -
examples/firehose/src/main.rs | 207 +++++----
examples/firehose/src/stream.rs | 1 -
examples/firehose/src/stream/frames.rs | 158 -------
examples/firehose/src/subscription.rs | 13 -
30 files changed, 1505 insertions(+), 259 deletions(-)
create mode 100644 atrium-xrpc-wss-client/.gitignore
create mode 100644 atrium-xrpc-wss-client/CHANGELOG.md
create mode 100644 atrium-xrpc-wss-client/Cargo.toml
create mode 100644 atrium-xrpc-wss-client/README.md
create mode 100644 atrium-xrpc-wss-client/src/client.rs
create mode 100644 atrium-xrpc-wss-client/src/lib.rs
create mode 100644 atrium-xrpc-wss-client/src/subscriptions/mod.rs
create mode 100644 atrium-xrpc-wss-client/src/subscriptions/repositories/firehose.rs
create mode 100644 atrium-xrpc-wss-client/src/subscriptions/repositories/mod.rs
create mode 100644 atrium-xrpc-wss-client/src/subscriptions/repositories/type_defs.rs
create mode 100644 atrium-xrpc-wss/.gitignore
create mode 100644 atrium-xrpc-wss/CHANGELOG.md
create mode 100644 atrium-xrpc-wss/Cargo.toml
create mode 100644 atrium-xrpc-wss/README.md
create mode 100644 atrium-xrpc-wss/src/client/mod.rs
create mode 100644 atrium-xrpc-wss/src/client/xprc_uri.rs
create mode 100644 atrium-xrpc-wss/src/lib.rs
create mode 100644 atrium-xrpc-wss/src/subscriptions/frames/mod.rs
create mode 100644 atrium-xrpc-wss/src/subscriptions/frames/tests.rs
create mode 100644 atrium-xrpc-wss/src/subscriptions/handlers/mod.rs
create mode 100644 atrium-xrpc-wss/src/subscriptions/handlers/repositories.rs
create mode 100644 atrium-xrpc-wss/src/subscriptions/mod.rs
delete mode 100644 examples/firehose/src/lib.rs
delete mode 100644 examples/firehose/src/stream.rs
delete mode 100644 examples/firehose/src/stream/frames.rs
delete mode 100644 examples/firehose/src/subscription.rs
diff --git a/Cargo.lock b/Cargo.lock
index ea0fa279..b9d24778 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -96,6 +96,18 @@ version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+[[package]]
+name = "arrayref"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a"
+
+[[package]]
+name = "arrayvec"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
+
[[package]]
name = "assert-json-diff"
version = "2.0.2"
@@ -117,6 +129,28 @@ dependencies = [
"futures-core",
]
+[[package]]
+name = "async-stream"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.71",
+]
+
[[package]]
name = "async-trait"
version = "0.1.81"
@@ -197,6 +231,38 @@ dependencies = [
"wasm-bindgen-test",
]
+[[package]]
+name = "atrium-xrpc-wss"
+version = "0.1.0"
+dependencies = [
+ "atrium-api",
+ "cbor4ii",
+ "futures",
+ "ipld-core",
+ "serde",
+ "serde_ipld_dagcbor",
+ "thiserror",
+]
+
+[[package]]
+name = "atrium-xrpc-wss-client"
+version = "0.1.0"
+dependencies = [
+ "async-stream",
+ "atrium-xrpc",
+ "atrium-xrpc-wss",
+ "bon",
+ "futures",
+ "ipld-core",
+ "rs-car",
+ "serde",
+ "serde_html_form",
+ "serde_ipld_dagcbor",
+ "thiserror",
+ "tokio",
+ "tokio-tungstenite",
+]
+
[[package]]
name = "autocfg"
version = "1.3.0"
@@ -254,6 +320,17 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+[[package]]
+name = "blake2b_simd"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "constant_time_eq",
+]
+
[[package]]
name = "block-buffer"
version = "0.10.4"
@@ -263,6 +340,29 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "bon"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee4f37d875011af3196e4828024742a84dcff6b0d027d272f2944f9a99f2c8af"
+dependencies = [
+ "bon-macros",
+ "rustversion",
+]
+
+[[package]]
+name = "bon-macros"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99b4b686e7ebf76cfa591052482d8c3c8242722518560798631974bf899d5565"
+dependencies = [
+ "darling",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.71",
+]
+
[[package]]
name = "bsky-cli"
version = "0.1.22"
@@ -294,7 +394,7 @@ dependencies = [
"serde_json",
"thiserror",
"tokio",
- "toml",
+ "toml 0.8.15",
"unicode-segmentation",
]
@@ -304,6 +404,12 @@ version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
[[package]]
name = "bytes"
version = "1.6.1"
@@ -352,6 +458,19 @@ dependencies = [
"windows-targets 0.52.6",
]
+[[package]]
+name = "cid"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3"
+dependencies = [
+ "core2",
+ "multibase",
+ "multihash 0.18.1",
+ "serde",
+ "unsigned-varint 0.7.2",
+]
+
[[package]]
name = "cid"
version = "0.11.1"
@@ -360,7 +479,7 @@ checksum = "3147d8272e8fa0ccd29ce51194dd98f79ddfb8191ba9e3409884e751798acf3a"
dependencies = [
"core2",
"multibase",
- "multihash",
+ "multihash 0.19.1",
"serde",
"serde_bytes",
"unsigned-varint 0.8.0",
@@ -385,7 +504,7 @@ dependencies = [
"anstream",
"anstyle",
"clap_lex",
- "strsim",
+ "strsim 0.10.0",
]
[[package]]
@@ -447,6 +566,12 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+[[package]]
+name = "constant_time_eq"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
+
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -540,6 +665,41 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "darling"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim 0.11.1",
+ "syn 2.0.71",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn 2.0.71",
+]
+
[[package]]
name = "data-encoding"
version = "2.6.0"
@@ -736,6 +896,7 @@ checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
+ "futures-executor",
"futures-io",
"futures-sink",
"futures-task",
@@ -758,6 +919,17 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
+[[package]]
+name = "futures-executor"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
[[package]]
name = "futures-io"
version = "0.3.30"
@@ -779,6 +951,17 @@ dependencies = [
"waker-fn",
]
+[[package]]
+name = "futures-macro"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.71",
+]
+
[[package]]
name = "futures-sink"
version = "0.3.30"
@@ -797,11 +980,16 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
+ "futures-channel",
"futures-core",
+ "futures-io",
+ "futures-macro",
"futures-sink",
"futures-task",
+ "memchr",
"pin-project-lite",
"pin-utils",
+ "slab",
]
[[package]]
@@ -1082,6 +1270,12 @@ dependencies = [
"cc",
]
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
[[package]]
name = "idna"
version = "0.5.0"
@@ -1117,7 +1311,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ede82a79e134f179f4b29b5fdb1eb92bd1b38c4dfea394c539051150a21b9b"
dependencies = [
- "cid",
+ "cid 0.11.1",
"serde",
"serde_bytes",
]
@@ -1209,6 +1403,55 @@ version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
+[[package]]
+name = "libipld"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1ccd6b8ffb3afee7081fcaec00e1b099fd1c7ccf35ba5729d88538fcc3b4599"
+dependencies = [
+ "fnv",
+ "libipld-cbor",
+ "libipld-core",
+ "libipld-macro",
+ "log",
+ "multihash 0.18.1",
+ "thiserror",
+]
+
+[[package]]
+name = "libipld-cbor"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77d98c9d1747aa5eef1cf099cd648c3fd2d235249f5fed07522aaebc348e423b"
+dependencies = [
+ "byteorder",
+ "libipld-core",
+ "thiserror",
+]
+
+[[package]]
+name = "libipld-core"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5acd707e8d8b092e967b2af978ed84709eaded82b75effe6cb6f6cc797ef8158"
+dependencies = [
+ "anyhow",
+ "cid 0.10.1",
+ "core2",
+ "multibase",
+ "multihash 0.18.1",
+ "thiserror",
+]
+
+[[package]]
+name = "libipld-macro"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71171c54214f866ae6722f3027f81dff0931e600e5a61e6b1b6a49ca0b5ed4ae"
+dependencies = [
+ "libipld-core",
+]
+
[[package]]
name = "libnghttp2-sys"
version = "0.1.10+1.61.0"
@@ -1325,6 +1568,17 @@ dependencies = [
"data-encoding-macro",
]
+[[package]]
+name = "multihash"
+version = "0.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815"
+dependencies = [
+ "core2",
+ "multihash-derive",
+ "unsigned-varint 0.7.2",
+]
+
[[package]]
name = "multihash"
version = "0.19.1"
@@ -1336,6 +1590,20 @@ dependencies = [
"unsigned-varint 0.7.2",
]
+[[package]]
+name = "multihash-derive"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "synstructure",
+]
+
[[package]]
name = "native-tls"
version = "0.2.12"
@@ -1563,6 +1831,40 @@ dependencies = [
"elliptic-curve",
]
+[[package]]
+name = "proc-macro-crate"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
+dependencies = [
+ "thiserror",
+ "toml 0.5.11",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
[[package]]
name = "proc-macro2"
version = "1.0.86"
@@ -1792,6 +2094,18 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "rs-car"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf69c4017006c0101362b5df74ee230331703e9938f970468dc1e429afe12998"
+dependencies = [
+ "blake2b_simd",
+ "futures",
+ "libipld",
+ "sha2",
+]
+
[[package]]
name = "rustc-demangle"
version = "0.1.24"
@@ -1864,6 +2178,12 @@ dependencies = [
"untrusted",
]
+[[package]]
+name = "rustversion"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
+
[[package]]
name = "ryu"
version = "1.0.18"
@@ -2014,6 +2334,17 @@ dependencies = [
"serde",
]
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
[[package]]
name = "sha2"
version = "0.10.8"
@@ -2108,6 +2439,12 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
[[package]]
name = "subtle"
version = "2.6.1"
@@ -2142,6 +2479,18 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
+[[package]]
+name = "synstructure"
+version = "0.12.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "unicode-xid",
+]
+
[[package]]
name = "tempfile"
version = "3.10.1"
@@ -2240,6 +2589,20 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "tokio-tungstenite"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38"
+dependencies = [
+ "futures-util",
+ "log",
+ "native-tls",
+ "tokio",
+ "tokio-native-tls",
+ "tungstenite",
+]
+
[[package]]
name = "tokio-util"
version = "0.7.11"
@@ -2253,6 +2616,15 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "toml"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "toml"
version = "0.8.15"
@@ -2362,6 +2734,26 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+[[package]]
+name = "tungstenite"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1"
+dependencies = [
+ "byteorder",
+ "bytes",
+ "data-encoding",
+ "http 1.1.0",
+ "httparse",
+ "log",
+ "native-tls",
+ "rand",
+ "sha1",
+ "thiserror",
+ "url",
+ "utf-8",
+]
+
[[package]]
name = "typenum"
version = "1.17.0"
@@ -2395,6 +2787,12 @@ version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
+[[package]]
+name = "unicode-xid"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a"
+
[[package]]
name = "unsigned-varint"
version = "0.7.2"
@@ -2424,6 +2822,12 @@ dependencies = [
"percent-encoding",
]
+[[package]]
+name = "utf-8"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
+
[[package]]
name = "utf8parse"
version = "0.2.2"
diff --git a/Cargo.toml b/Cargo.toml
index ffacaf5e..6f9c9698 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,6 +4,8 @@ members = [
"atrium-crypto",
"atrium-xrpc",
"atrium-xrpc-client",
+ "atrium-xrpc-wss",
+ "atrium-xrpc-wss-client",
"bsky-cli",
"bsky-sdk",
]
@@ -26,6 +28,8 @@ keywords = ["atproto", "bluesky"]
atrium-api = { version = "0.24.4", path = "atrium-api" }
atrium-xrpc = { version = "0.11.3", path = "atrium-xrpc" }
atrium-xrpc-client = { version = "0.5.6", path = "atrium-xrpc-client" }
+atrium-xrpc-wss = { version = "0.1.0", path = "atrium-xrpc-wss" }
+atrium-xrpc-wss-client = { version = "0.1.0", path = "atrium-xrpc-wss-client" }
bsky-sdk = { version = "0.1.9", path = "bsky-sdk" }
# async in traits
@@ -35,6 +39,10 @@ async-trait = "0.1.80"
# DAG-CBOR codec
ipld-core = { version = "0.4.1", default-features = false, features = ["std"] }
serde_ipld_dagcbor = { version = "0.6.0", default-features = false, features = ["std"] }
+cbor4ii = { version = "0.2.14", default-features = false }
+
+# CAR files
+rs-car = "0.4.1"
# Parsing and validation
chrono = "0.4"
@@ -55,8 +63,10 @@ rand = "0.8.5"
# Networking
futures = { version = "0.3.30", default-features = false, features = ["alloc"] }
+async-stream = "0.3.5"
http = "1.1.0"
tokio = { version = "1.37", default-features = false }
+tokio-tungstenite = { version = "0.21.0", features = ["native-tls"] }
# HTTP client integrations
isahc = "1.7.2"
@@ -76,3 +86,6 @@ mockito = "1.4"
# WebAssembly
wasm-bindgen-test = "0.3.41"
bumpalo = "~3.14.0"
+
+# Code generation
+bon = "2.2.1"
\ No newline at end of file
diff --git a/atrium-xrpc-wss-client/.gitignore b/atrium-xrpc-wss-client/.gitignore
new file mode 100644
index 00000000..4fffb2f8
--- /dev/null
+++ b/atrium-xrpc-wss-client/.gitignore
@@ -0,0 +1,2 @@
+/target
+/Cargo.lock
diff --git a/atrium-xrpc-wss-client/CHANGELOG.md b/atrium-xrpc-wss-client/CHANGELOG.md
new file mode 100644
index 00000000..df3cff36
--- /dev/null
+++ b/atrium-xrpc-wss-client/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
\ No newline at end of file
diff --git a/atrium-xrpc-wss-client/Cargo.toml b/atrium-xrpc-wss-client/Cargo.toml
new file mode 100644
index 00000000..cdb6306b
--- /dev/null
+++ b/atrium-xrpc-wss-client/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+name = "atrium-xrpc-wss-client"
+version = "0.1.0"
+authors = ["Elaina <17bestradiol@proton.me>"]
+edition.workspace = true
+rust-version.workspace = true
+description = "XRPC Websocket Client library for AT Protocol (Bluesky)"
+documentation = "https://docs.rs/atrium-xrpc-wss-client"
+readme = "README.md"
+repository.workspace = true
+license.workspace = true
+keywords.workspace = true
+
+[dependencies]
+atrium-xrpc.workspace = true
+atrium-xrpc-wss.workspace = true
+futures.workspace = true
+ipld-core.workspace = true
+async-stream.workspace = true
+tokio-tungstenite.workspace = true
+serde_ipld_dagcbor.workspace = true
+rs-car.workspace = true
+tokio.workspace = true
+bon.workspace = true
+serde_html_form.workspace = true
+serde.workspace = true
+thiserror.workspace = true
\ No newline at end of file
diff --git a/atrium-xrpc-wss-client/README.md b/atrium-xrpc-wss-client/README.md
new file mode 100644
index 00000000..5e919be9
--- /dev/null
+++ b/atrium-xrpc-wss-client/README.md
@@ -0,0 +1 @@
+# ATrium XRPC WSS Client
\ No newline at end of file
diff --git a/atrium-xrpc-wss-client/src/client.rs b/atrium-xrpc-wss-client/src/client.rs
new file mode 100644
index 00000000..1db7c11f
--- /dev/null
+++ b/atrium-xrpc-wss-client/src/client.rs
@@ -0,0 +1,87 @@
+//! This file provides a client for the `ATProto` XRPC over WSS protocol.
+//! It implements the [`WssClient`] trait for the [`XrpcWssClient`] struct.
+
+use std::str::FromStr;
+
+use futures::Stream;
+use tokio::net::TcpStream;
+
+use atrium_xrpc::{
+ http::{Request, Uri},
+ types::Header,
+};
+use bon::Builder;
+use serde::Serialize;
+use tokio_tungstenite::{
+ connect_async,
+ tungstenite::{self, handshake::client::generate_key},
+ MaybeTlsStream, WebSocketStream,
+};
+
+use atrium_xrpc_wss::client::{WssClient, XrpcUri};
+
+/// An enum of possible error kinds for this crate.
+#[derive(thiserror::Error, Debug)]
+pub enum Error {
+ #[error("Invalid uri")]
+ InvalidUri,
+ #[error("Parsing parameters failed: {0}")]
+ ParsingParameters(#[from] serde_html_form::ser::Error),
+ #[error("Connection error: {0}")]
+ Connection(#[from] tungstenite::Error),
+}
+
+#[derive(Builder)]
+pub struct XrpcWssClient<'a, P: Serialize> {
+ xrpc_uri: XrpcUri<'a>,
+ params: Option
,
+}
+
+type StreamKind = WebSocketStream>;
+impl WssClient<::Item, Error>
+ for XrpcWssClient<'_, P>
+{
+ async fn connect(&self) -> Result::Item>, Error> {
+ let Self { xrpc_uri, params } = self;
+ let mut uri = xrpc_uri.to_uri();
+ //// Query parameters
+ if let Some(p) = ¶ms {
+ uri.push('?');
+ uri += &serde_html_form::to_string(p)?;
+ };
+ ////
+
+ //// Request
+ // Extracting the authority from the URI to set the Host header.
+ let uri = Uri::from_str(&uri).map_err(|_| Error::InvalidUri)?;
+ let authority = uri.authority().ok_or_else(|| Error::InvalidUri)?.as_str();
+ let host = authority
+ .find('@')
+ .map_or_else(|| authority, |idx| authority.split_at(idx + 1).1);
+
+ // Building the request.
+ let mut request = Request::builder()
+ .uri(&uri)
+ .method("GET")
+ .header("Host", host)
+ .header("Connection", "Upgrade")
+ .header("Upgrade", "websocket")
+ .header("Sec-WebSocket-Version", "13")
+ .header("Sec-WebSocket-Key", generate_key());
+
+ // Adding the ATProto headers.
+ if let Some(proxy) = self.atproto_proxy_header().await {
+ request = request.header(Header::AtprotoProxy, proxy);
+ }
+ if let Some(accept_labelers) = self.atproto_accept_labelers_header().await {
+ request = request.header(Header::AtprotoAcceptLabelers, accept_labelers.join(", "));
+ }
+
+ // In our case, the only thing that could possibly fail is the URI. The headers are all `String`/`&str`.
+ let request = request.body(()).map_err(|_| Error::InvalidUri)?;
+ ////
+
+ let (stream, _) = connect_async(request).await?;
+ Ok(stream)
+ }
+}
diff --git a/atrium-xrpc-wss-client/src/lib.rs b/atrium-xrpc-wss-client/src/lib.rs
new file mode 100644
index 00000000..ed422338
--- /dev/null
+++ b/atrium-xrpc-wss-client/src/lib.rs
@@ -0,0 +1,6 @@
+mod client;
+pub use client::{Error, XrpcWssClient};
+
+pub mod subscriptions;
+
+pub use atrium_xrpc_wss; // Re-export the atrium_xrpc_wss crate
\ No newline at end of file
diff --git a/atrium-xrpc-wss-client/src/subscriptions/mod.rs b/atrium-xrpc-wss-client/src/subscriptions/mod.rs
new file mode 100644
index 00000000..21b552a0
--- /dev/null
+++ b/atrium-xrpc-wss-client/src/subscriptions/mod.rs
@@ -0,0 +1 @@
+pub mod repositories;
diff --git a/atrium-xrpc-wss-client/src/subscriptions/repositories/firehose.rs b/atrium-xrpc-wss-client/src/subscriptions/repositories/firehose.rs
new file mode 100644
index 00000000..c7727f0f
--- /dev/null
+++ b/atrium-xrpc-wss-client/src/subscriptions/repositories/firehose.rs
@@ -0,0 +1,225 @@
+use std::{collections::BTreeMap, io::Cursor};
+
+use futures::io::Cursor as FutCursor;
+use ipld_core::cid::Cid;
+
+use super::type_defs::{self, Operation};
+use atrium_xrpc_wss::{
+ atrium_api::{
+ com::atproto::sync::subscribe_repos::{self, CommitData, InfoData, RepoOpData},
+ record::KnownRecord,
+ types::Object,
+ },
+ subscriptions::{
+ handlers::repositories::{HandledData, Handler, ProcessedData},
+ ConnectionHandler, ProcessedPayload,
+ }
+};
+
+/// Errors for this crate
+#[derive(Debug, thiserror::Error)]
+pub enum HandlingError {
+ #[error("CAR Decoding error: {0}")]
+ CarDecoding(#[from] rs_car::CarDecodeError),
+ #[error("IPLD Decoding error: {0}")]
+ IpldDecoding(#[from] serde_ipld_dagcbor::DecodeError),
+}
+
+pub struct Firehose;
+impl ConnectionHandler for Firehose {
+ type HandledData = HandledData;
+ type HandlingError = self::HandlingError;
+
+ async fn handle_payload(
+ &self,
+ t: String,
+ payload: Vec,
+ ) -> Result