Full Code of emreyalvac/firebase-rs for AI

master ef20b98c626f cached
11 files
24.3 KB
6.3k tokens
63 symbols
1 requests
Download .txt
Repository: emreyalvac/firebase-rs
Branch: master
Commit: ef20b98c626f
Files: 11
Total size: 24.3 KB

Directory structure:
gitextract_6kyzg2xz/

├── .cargo/
│   └── config
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
└── src/
    ├── constants.rs
    ├── errors.rs
    ├── lib.rs
    ├── params.rs
    ├── sse.rs
    └── utils.rs

================================================
FILE CONTENTS
================================================

================================================
FILE: .cargo/config
================================================
[alias]
t = "test -- --nocapture"


================================================
FILE: .gitignore
================================================
/target
.idea

================================================
FILE: Cargo.toml
================================================
[package]
name = "firebase-rs"
edition = "2021"
version = "2.2.5"
description = "Rust based Firebase library"
readme = "README.md"
repository = "https://github.com/emreyalvac/firebase-rs"
documentation = "https://docs.rs/firebase-rs/2.2.5/firebase_rs/"
license = "MIT"
authors = ["Emre YALVAÇ <emre.yalvac@outlook.com>"]
exclude = ["examples/*", "tests/*"]
keywords = ["firebase", "rest", "api", "web", "database"]

[dependencies]
url = "2.2.3"
reqwest = { version = "0.12.12", features = ["json"] }
serde_json = "1.0.137"
serde = { version = "1.0.217", features = ["derive"] }
itertools = "0.14.0"
eventsource-client = "0.13.0"
futures-util = "0.3.31"

[dev-dependencies]
tokio = { version = "1.43.0", features = ["rt", "macros", "rt-multi-thread"] }

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 Emre YALVAÇ

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# firebase-rs

[![Crates.io](https://img.shields.io/crates/v/firebase-rs.svg)](https://crates.io/crates/firebase-rs) [![docs.rs](https://docs.rs/firebase-rs/badge.svg)](https://docs.rs/firebase-rs) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)

Rust based Firebase library.
---
![firebase](https://firebase.google.com/downloads/brand-guidelines/SVG/logo-logomark.svg 'Firebase')

# Full Documentation

[Documentation](https://docs.rs/firebase-rs/2.2.5/firebase_rs/)

# Features

- Server-Sent Events (a.k.a stream) (https://github.com/emreyalvac/firebase-rs#read-data-as-stream)
- Generic Payload

# How to use

### Load library

````rust
use firebase_rs::*;
````

### Without Auth

````rust
let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap();
````

### With Auth

````rust
let firebase = Firebase::auth("https://myfirebase.firebaseio.com", "AUTH_KEY").unwrap();
````

---

### At usage for nested objects

````rust
let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users").at("USER_ID").at(...);
````

---

### Read Data as Stream

### With Real Time Events

````rust
let firebase = Firebase::new("https://myfirebase.firebaseio.com").at("users").unwrap();
let stream = firebase.with_realtime_events().unwrap();
stream
.listen( | event_type, data| {
println ! ("Type: {:?} Data: {:?}", event_type, data);
}, | err| println!("{:?}", err), false).await;
````

### Read Data

#### Read data as string

````rust
let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users");
let users = firebase.get_as_string().await;
````

#### Read data with generic type (All)

````rust
#[derive(Serialize, Deserialize, Debug)]
struct User {
    name: String
}

let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users");
let user = firebase.get::<HashMap<String, User>> ().await;
````

#### Read data with generic type (Single record)

````rust
#[derive(Serialize, Deserialize, Debug)]
struct User {
    name: String
}

let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users").at("USER_ID");
let user = firebase.get::<User>().await;
````

---

### Set Data with Custom Key

````rust
#[derive(Serialize, Deserialize, Debug)]
struct User {
    name: String
}

let user = User { name: String::default () };
let mut firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users");
firebase.set_with_key("myKey", &user).await;
````
_Output_
```json
{
  "users": {
    "myKey": {
      "name": ""
    }
  }
}
```

### Set Data

````rust
#[derive(Serialize, Deserialize, Debug)]
struct User {
    name: String
}

let user = User { name: String::default () };
let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users");
firebase.set(&user).await;
````
_Output_
```json
{
  "users": {
    "-OC9mYIUIdY3JygkmsFQ": {
      "name": ""
    }
  }
}
```

---

### Update Data

````rust
#[derive(Serialize, Deserialize, Debug)]
struct User {
    name: String
}

let user = User { name: String::default () };
let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users").at("USER_ID");
firebase.update( &user).await;
````

---

### With Params

````rust
let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().with_params().start_at(1).order_by("name").equal_to(5).finish();
let result = firebase.get().await;
````

## Contributors

Thanks goes to these wonderful people ✨

<a href="https://github.com/emreyalvac/firebase-rs/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=emreyalvac/firebase-rs" />
</a>



================================================
FILE: src/constants.rs
================================================
pub const AUTH: &str = "auth";
pub const ORDER_BY: &str = "orderBy";
pub const LIMIT_TO_FIRST: &str = "limitToFirst";
pub const LIMIT_TO_LAST: &str = "limitToLast";
pub const START_AT: &str = "startAt";
pub const END_AT: &str = "endAt";
pub const EQUAL_TO: &str = "equalTo";
pub const SHALLOW: &str = "shallow";
pub const FORMAT: &str = "format";
pub const EXPORT: &str = "export";

#[derive(Debug, PartialEq)]
pub enum Method {
    GET,
    POST,
    DELETE,
    PATCH,
    PUT,
}

#[derive(Debug)]
pub struct Response {
    pub data: String,
}

impl Response {
    pub fn new() -> Self {
        Self {
            data: String::default(),
        }
    }
}


================================================
FILE: src/errors.rs
================================================
use std::{
    error::Error,
    fmt::{Display, Formatter},
};

pub type UrlParseResult<T> = Result<T, UrlParseError>;

#[derive(Debug)]
#[non_exhaustive]
pub enum UrlParseError {
    NoPath,
    NotHttps,
    Parser(url::ParseError),
}

impl Error for UrlParseError {}

impl Display for UrlParseError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            UrlParseError::NoPath => write!(f, "URL path is missing."),
            UrlParseError::NotHttps => write!(f, "The URL protocol should be https."),
            UrlParseError::Parser(e) => write!(f, "Error while parsing the URL: {}", e),
        }
    }
}

pub type RequestResult<T> = Result<T, RequestError>;

#[derive(Debug)]
#[non_exhaustive]
pub enum RequestError {
    NotJSON,
    NoUTF8,
    NetworkError,
    SerializeError(serde_json::Error),
    DeserializeError(serde_json::Error),
    NotFoundOrNullBody,
    Unauthorized,
}

impl Error for RequestError {}

impl Display for RequestError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            RequestError::NotJSON => write!(f, "Invalid JSON"),
            RequestError::NoUTF8 => write!(f, "Utf8 error"),
            RequestError::NetworkError => write!(f, "Network error"),
            RequestError::SerializeError(e) => write!(f, "Failed to serialize request: {}", e),
            RequestError::DeserializeError(e) => write!(f, "Failed to deserialize response: {}", e),
            RequestError::NotFoundOrNullBody => write!(f, "Body is null or record is not found"),
            RequestError::Unauthorized => write!(f, "Unauthorized"),
        }
    }
}

#[derive(Debug)]
#[non_exhaustive]
pub enum ServerEventError {
    ConnectionError,
}

impl Error for ServerEventError {}

impl Display for ServerEventError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            ServerEventError::ConnectionError => write!(f, "Connection error for server events"),
        }
    }
}


================================================
FILE: src/lib.rs
================================================
use constants::{Method, Response, AUTH};
use errors::{RequestResult, UrlParseResult};
use params::Params;
use reqwest::StatusCode;
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json::Value;
use std::fmt::Debug;
use url::Url;
use utils::check_uri;

use crate::sse::ServerEvents;

pub use errors::{RequestError, ServerEventError, UrlParseError};

mod constants;
mod errors;
mod params;
mod sse;
mod utils;

#[derive(Debug)]
pub struct Firebase {
    uri: Url,
}

impl Firebase {
    /// ```rust
    /// use firebase_rs::Firebase;
    ///
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap();
    /// ```
    pub fn new(uri: &str) -> UrlParseResult<Self>
    where
        Self: Sized,
    {
        match check_uri(&uri) {
            Ok(uri) => Ok(Self { uri }),
            Err(err) => Err(err),
        }
    }

    /// ```rust
    /// const URI: &str = "...";
    /// const AUTH_KEY: &str = "...";
    ///
    /// use firebase_rs::Firebase;
    ///
    /// let firebase = Firebase::auth("https://myfirebase.firebaseio.com", AUTH_KEY).unwrap();
    /// ```
    pub fn auth(uri: &str, auth_key: &str) -> UrlParseResult<Self>
    where
        Self: Sized,
    {
        match check_uri(&uri) {
            Ok(mut uri) => {
                uri.set_query(Some(&format!("{}={}", AUTH, auth_key)));
                Ok(Self { uri })
            }
            Err(err) => Err(err),
        }
    }

    /// ```rust
    /// use firebase_rs::Firebase;
    ///
    /// # async fn run() {
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().with_params().start_at(1).order_by("name").equal_to(5).finish();
    /// let result = firebase.get::<String>().await;
    /// # }
    /// ```
    pub fn with_params(&self) -> Params {
        let uri = self.uri.clone();
        Params::new(uri)
    }

    /// To use simple interface with synchronous callbacks, pair with `.listen()`:
    /// ```rust
    /// use firebase_rs::Firebase;
    /// # async fn run() {
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users");
    /// let stream = firebase.with_realtime_events().unwrap();
    /// stream.listen(|event_type, data| {
    ///                     println!("{:?} {:?}" ,event_type, data);
    ///                 }, |err| println!("{:?}" ,err), false).await;
    /// # }
    /// ```
    ///
    /// To use streaming interface for async code, pair with `.stream()`:
    /// ```rust
    /// use firebase_rs::Firebase;
    /// use futures_util::StreamExt;
    ///
    /// # async fn run() {
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users");
    /// let stream = firebase.with_realtime_events()
    ///              .unwrap()
    ///              .stream(true);
    /// stream.for_each(|event| {
    ///           match event {
    ///               Ok((event_type, maybe_data)) => println!("{:?} {:?}" ,event_type, maybe_data),
    ///               Err(err) => println!("{:?}" ,err),
    ///           }
    ///           futures_util::future::ready(())
    ///        }).await;
    /// # }
    /// ```
    pub fn with_realtime_events(&self) -> Option<ServerEvents> {
        ServerEvents::new(self.uri.as_str())
    }

    /// ```rust
    /// use firebase_rs::Firebase;
    ///
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users").at("USER_ID").at("f69111a8a5258c15286d3d0bd4688c55");
    /// ```
    pub fn at(&self, path: &str) -> Self {
        let uri = self.build_uri(path);

        Firebase { uri }
    }

    fn build_uri(&self, path: &str) -> Url {
        let mut new_path = String::new();

        if let Some(segments) = self.uri.path_segments() {
            for segment in segments {
                let clean_segment = segment.trim_end_matches(".json");
                new_path.push_str(clean_segment);
                new_path.push('/');
            }
        }

        new_path.push_str(path);

        let final_path = if new_path.ends_with(".json") {
            new_path.trim_end_matches(".json").to_string()
        } else {
            new_path
        };

        let mut uri = self.uri.clone();
        uri.set_path(&format!("{}.json", final_path));

        uri
    }

    /// ```rust
    /// use firebase_rs::Firebase;
    ///
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users");
    /// let uri = firebase.get_uri();
    /// ```
    pub fn get_uri(&self) -> String {
        self.uri.to_string()
    }

    async fn request(&self, method: Method, data: Option<Value>) -> RequestResult<Response> {
        let client = reqwest::Client::new();
        let request = match method {
            Method::GET => client.get(self.uri.to_string()).send().await,
            Method::PUT | Method::PATCH | Method::POST => {
                if data.is_none() {
                    return Err(RequestError::NotFoundOrNullBody);
                }
                let builder = if method == Method::PUT {
                    client.put(self.uri.to_string())
                } else if method == Method::POST {
                    client.post(self.uri.to_string())
                } else {
                    client.patch(self.uri.to_string())
                };
                builder.json(&data).send().await
            }
            Method::DELETE => client.delete(self.uri.to_string()).send().await,
        };

        match request {
            Ok(response) => match response.status() {
                StatusCode::OK | StatusCode::NO_CONTENT => {
                    let response_text = response.text().await.unwrap_or_default();
                    Ok(Response {
                        data: response_text,
                    })
                }
                StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN => Err(RequestError::Unauthorized),
                StatusCode::NOT_FOUND => Err(RequestError::NotFoundOrNullBody),
                _ => Err(RequestError::NetworkError),
            },
            Err(_) => Err(RequestError::NetworkError),
        }
    }

    async fn request_generic<T>(&self, method: Method) -> RequestResult<T>
    where
        T: DeserializeOwned + Debug,
    {
        let request = self.request(method, None).await;

        match request {
            Ok(response) => {
                let value: serde_json::Value = serde_json::from_str(response.data.as_str())
                    .map_err(|_| RequestError::NotJSON)?;

                let data: T = serde_json::from_value(value)
                    .map_err(RequestError::DeserializeError)?;

                Ok(data)
            }
            Err(err) => Err(err),
        }
    }

    /// ```rust
    /// use firebase_rs::Firebase;
    /// use serde::{Serialize, Deserialize};
    ///
    /// #[derive(Serialize, Deserialize, Debug)]
    /// struct User {
    ///    name: String
    /// }
    ///
    /// # async fn run() {
    /// let user = User { name: String::default() };
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users");
    /// let users = firebase.set(&user).await;
    /// # }
    /// ```
    pub async fn set<T>(&self, data: &T) -> RequestResult<Response>
    where
        T: Serialize + Debug,
    {
        let data = serde_json::to_value(&data).map_err(RequestError::SerializeError)?;
        self.request(Method::POST, Some(data)).await
    }

    /// ```rust
    /// use firebase_rs::Firebase;
    /// use serde::{Serialize, Deserialize};
    ///
    /// #[derive(Serialize, Deserialize, Debug)]
    /// struct User {
    ///    name: String
    /// }
    ///
    /// # async fn run() {
    /// let user = User { name: String::default() };
    /// let mut firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users");
    /// let users = firebase.set_with_key("myKey", &user).await;
    /// # }
    /// ```
    pub async fn set_with_key<T>(&mut self, key: &str, data: &T) -> RequestResult<Response>
    where
        T: Serialize + Debug,
    {
        self.uri = self.build_uri(key);
        let data = serde_json::to_value(&data).map_err(RequestError::SerializeError)?;

        self.request(Method::PUT, Some(data)).await
    }

    /// ```rust
    /// use std::collections::HashMap;
    /// use firebase_rs::Firebase;
    /// use serde::{Serialize, Deserialize};
    ///
    /// #[derive(Serialize, Deserialize, Debug)]
    /// struct User {
    ///    name: String
    /// }
    ///
    /// # async fn run() {
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users");
    /// let users = firebase.get::<HashMap<String, User>>().await;
    /// # }
    /// ```
    pub async fn get_as_string(&self) -> RequestResult<Response> {
        self.request(Method::GET, None).await
    }

    /// ```rust
    /// use std::collections::HashMap;
    /// use firebase_rs::Firebase;
    /// use serde::{Serialize, Deserialize};
    ///
    /// #[derive(Serialize, Deserialize, Debug)]
    /// struct User {
    ///     name: String
    /// }
    ///
    /// # async fn run() {
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users").at("USER_ID");
    /// let user = firebase.get::<User>().await;
    ///
    ///  // OR
    ///
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users");
    /// let user = firebase.get::<HashMap<String, User>>().await;
    /// # }
    /// ```
    pub async fn get<T>(&self) -> RequestResult<T>
    where
        T: DeserializeOwned + Debug,
    {
        self.request_generic::<T>(Method::GET).await
    }

    /// ```rust
    /// use firebase_rs::Firebase;
    ///
    /// # async fn run() {
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users").at("USER_ID");
    /// firebase.delete().await;
    /// # }
    /// ```
    pub async fn delete(&self) -> RequestResult<Response> {
        self.request(Method::DELETE, None).await
    }

    /// ```rust
    /// use firebase_rs::Firebase;
    /// use serde::{Serialize, Deserialize};
    ///
    /// #[derive(Serialize, Deserialize, Debug)]
    /// struct User {
    ///     name: String
    /// }
    ///
    /// # async fn run() {
    /// let user = User { name: String::default() };
    /// let firebase = Firebase::new("https://myfirebase.firebaseio.com").unwrap().at("users").at("USER_ID");
    /// let users = firebase.update(&user).await;
    /// # }
    /// ```
    pub async fn update<T>(&self, data: &T) -> RequestResult<Response>
    where
        T: Serialize + Debug,
    {
        let value = serde_json::to_value(&data).map_err(RequestError::SerializeError)?;
        self.request(Method::PATCH, Some(value)).await
    }
}

#[cfg(test)]
mod tests {
    use crate::{Firebase, UrlParseError};

    const URI: &str = "https://firebase_id.firebaseio.com";
    const URI_WITH_SLASH: &str = "https://firebase_id.firebaseio.com/";
    const URI_NON_HTTPS: &str = "http://firebase_id.firebaseio.com/";

    #[tokio::test]
    async fn simple() {
        let firebase = Firebase::new(URI).unwrap();
        assert_eq!(URI_WITH_SLASH.to_string(), firebase.get_uri());
    }

    #[tokio::test]
    async fn non_https() {
        let firebase = Firebase::new(URI_NON_HTTPS).map_err(|e| e.to_string());
        assert_eq!(
            firebase.err(),
            Some(String::from(UrlParseError::NotHttps.to_string()))
        );
    }

    #[tokio::test]
    async fn with_auth() {
        let firebase = Firebase::auth(URI, "auth_key").unwrap();
        assert_eq!(
            format!("{}/?auth=auth_key", URI.to_string()),
            firebase.get_uri()
        );
    }

    #[tokio::test]
    async fn with_sse_events() {
        // TODO: SSE Events Test
    }
}


================================================
FILE: src/params.rs
================================================
use crate::constants::{
    END_AT, EQUAL_TO, EXPORT, FORMAT, LIMIT_TO_FIRST, LIMIT_TO_LAST, ORDER_BY, SHALLOW, START_AT,
};
use crate::Firebase;
use itertools::Itertools;
use std::collections::HashMap;
use url::Url;

#[derive(Debug)]
pub struct Params {
    pub uri: Url,
    pub params: HashMap<String, String>,
}

impl Params {
    pub fn new(uri: Url) -> Self {
        Self {
            uri,
            params: Default::default(),
        }
    }

    pub fn set_params(&mut self) -> () {
        for (k, v) in self.params.iter().sorted() {
            self.uri.query_pairs_mut().append_pair(k, v);
        }
    }

    pub fn add_param<T>(&mut self, key: &str, value: T) -> &mut Self
    where
        T: ToString,
    {
        self.params.insert(key.to_string(), value.to_string());
        self.set_params();

        self
    }

    pub fn order_by(&mut self, key: &str) -> &mut Params {
        self.add_param(ORDER_BY, key)
    }

    pub fn limit_to_first(&mut self, count: u32) -> &mut Params {
        self.add_param(LIMIT_TO_FIRST, count)
    }

    pub fn limit_to_last(&mut self, count: u32) -> &mut Params {
        self.add_param(LIMIT_TO_LAST, count)
    }

    pub fn start_at(&mut self, index: u32) -> &mut Params {
        self.add_param(START_AT, index)
    }

    pub fn end_at(&mut self, index: u32) -> &mut Params {
        self.add_param(END_AT, index)
    }

    pub fn equal_to(&mut self, value: u32) -> &mut Params {
        self.add_param(EQUAL_TO, value)
    }

    pub fn shallow(&mut self, flag: bool) -> &mut Params {
        self.add_param(SHALLOW, flag)
    }

    pub fn format(&mut self) -> &mut Params {
        self.add_param(FORMAT, EXPORT)
    }

    pub fn finish(&self) -> Firebase {
        Firebase::new(self.uri.as_str()).unwrap()
    }
}

#[cfg(test)]
mod tests {
    use crate::params::Params;
    use std::collections::HashMap;
    use url::Url;

    #[test]
    fn check_params() {
        let mut params: HashMap<String, String> = HashMap::new();
        params.insert("param_1".to_owned(), "value_1".to_owned());
        params.insert("param_2".to_owned(), "value_2".to_owned());
        let mut param = Params {
            uri: Url::parse("https://github.com/emreyalvac").unwrap(),
            params,
        };
        param.set_params();

        assert_eq!(
            param.uri.as_str(),
            "https://github.com/emreyalvac?param_1=value_1&param_2=value_2"
        )
    }
}


================================================
FILE: src/sse.rs
================================================
use eventsource_client::*;
use futures_util::StreamExt;

pub struct ServerEvents {
    client: ClientBuilder,
}

impl ServerEvents {
    pub fn new(url: &str) -> Option<Self> {
        let client = ClientBuilder::for_url(url);

        match client {
            Ok(stream_connection) => Some(ServerEvents {
                client: stream_connection,
            }),
            Err(_) => None,
        }
    }

    pub async fn listen(
        self,
        stream_event: impl Fn(String, Option<String>),
        stream_err: impl Fn(Error),
        keep_alive_friendly: bool,
    ) {
        self.stream(keep_alive_friendly)
            .for_each(|event| {
                match event {
                    Ok((event_type, maybe_data)) => stream_event(event_type, maybe_data),
                    Err(x) => stream_err(x),
                }
                futures_util::future::ready(())
            })
            .await
    }

    pub fn stream(
        self,
        keep_alive_friendly: bool,
    ) -> std::pin::Pin<Box<dyn futures_util::Stream<Item = Result<(String, Option<String>)>> + Send>>
    {
        Box::pin(
            self.client
                .build()
                .stream()
                .filter_map(move |event| async move {
                    match event {
                        Ok(SSE::Event(ev)) => {
                            if ev.event_type == "keep-alive" && !keep_alive_friendly {
                                return None;
                            }

                            if ev.data == "null" {
                                return Some(Ok((ev.event_type, None)));
                            }

                            return Some(Ok((ev.event_type, Some(ev.data))));
                        }
                        Ok(SSE::Comment(_)) | Ok(SSE::Connected(_)) => return None,
                        Err(x) => Some(Err(x)),
                    }
                }),
        )
    }
}


================================================
FILE: src/utils.rs
================================================
use crate::errors::UrlParseResult;
use crate::UrlParseError;
use url::Url;

pub fn check_uri(uri: &str) -> UrlParseResult<Url> {
    let uri = Url::parse(uri);

    let uri = match uri {
        Ok(res) => res,
        Err(err) => return Err(UrlParseError::Parser(err)),
    };

    if uri.scheme() != "https" {
        return Err(UrlParseError::NotHttps);
    }

    Ok(uri)
}
Download .txt
gitextract_6kyzg2xz/

├── .cargo/
│   └── config
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
└── src/
    ├── constants.rs
    ├── errors.rs
    ├── lib.rs
    ├── params.rs
    ├── sse.rs
    └── utils.rs
Download .txt
SYMBOL INDEX (63 symbols across 6 files)

FILE: src/constants.rs
  constant AUTH (line 1) | pub const AUTH: &str = "auth";
  constant ORDER_BY (line 2) | pub const ORDER_BY: &str = "orderBy";
  constant LIMIT_TO_FIRST (line 3) | pub const LIMIT_TO_FIRST: &str = "limitToFirst";
  constant LIMIT_TO_LAST (line 4) | pub const LIMIT_TO_LAST: &str = "limitToLast";
  constant START_AT (line 5) | pub const START_AT: &str = "startAt";
  constant END_AT (line 6) | pub const END_AT: &str = "endAt";
  constant EQUAL_TO (line 7) | pub const EQUAL_TO: &str = "equalTo";
  constant SHALLOW (line 8) | pub const SHALLOW: &str = "shallow";
  constant FORMAT (line 9) | pub const FORMAT: &str = "format";
  constant EXPORT (line 10) | pub const EXPORT: &str = "export";
  type Method (line 13) | pub enum Method {
  type Response (line 22) | pub struct Response {
    method new (line 27) | pub fn new() -> Self {

FILE: src/errors.rs
  type UrlParseResult (line 6) | pub type UrlParseResult<T> = Result<T, UrlParseError>;
  type UrlParseError (line 10) | pub enum UrlParseError {
  method fmt (line 19) | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  type RequestResult (line 28) | pub type RequestResult<T> = Result<T, RequestError>;
  type RequestError (line 32) | pub enum RequestError {
  method fmt (line 45) | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  type ServerEventError (line 60) | pub enum ServerEventError {
  method fmt (line 67) | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {

FILE: src/lib.rs
  type Firebase (line 23) | pub struct Firebase {
    method new (line 33) | pub fn new(uri: &str) -> UrlParseResult<Self>
    method auth (line 51) | pub fn auth(uri: &str, auth_key: &str) -> UrlParseResult<Self>
    method with_params (line 72) | pub fn with_params(&self) -> Params {
    method with_realtime_events (line 108) | pub fn with_realtime_events(&self) -> Option<ServerEvents> {
    method at (line 117) | pub fn at(&self, path: &str) -> Self {
    method build_uri (line 123) | fn build_uri(&self, path: &str) -> Url {
    method get_uri (line 154) | pub fn get_uri(&self) -> String {
    method request (line 158) | async fn request(&self, method: Method, data: Option<Value>) -> Reques...
    method request_generic (line 194) | async fn request_generic<T>(&self, method: Method) -> RequestResult<T>
    method set (line 229) | pub async fn set<T>(&self, data: &T) -> RequestResult<Response>
    method set_with_key (line 252) | pub async fn set_with_key<T>(&mut self, key: &str, data: &T) -> Reques...
    method get_as_string (line 277) | pub async fn get_as_string(&self) -> RequestResult<Response> {
    method get (line 301) | pub async fn get<T>(&self) -> RequestResult<T>
    method delete (line 316) | pub async fn delete(&self) -> RequestResult<Response> {
    method update (line 335) | pub async fn update<T>(&self, data: &T) -> RequestResult<Response>
  constant URI (line 348) | const URI: &str = "https://firebase_id.firebaseio.com";
  constant URI_WITH_SLASH (line 349) | const URI_WITH_SLASH: &str = "https://firebase_id.firebaseio.com/";
  constant URI_NON_HTTPS (line 350) | const URI_NON_HTTPS: &str = "http://firebase_id.firebaseio.com/";
  function simple (line 353) | async fn simple() {
  function non_https (line 359) | async fn non_https() {
  function with_auth (line 368) | async fn with_auth() {
  function with_sse_events (line 377) | async fn with_sse_events() {

FILE: src/params.rs
  type Params (line 10) | pub struct Params {
    method new (line 16) | pub fn new(uri: Url) -> Self {
    method set_params (line 23) | pub fn set_params(&mut self) -> () {
    method add_param (line 29) | pub fn add_param<T>(&mut self, key: &str, value: T) -> &mut Self
    method order_by (line 39) | pub fn order_by(&mut self, key: &str) -> &mut Params {
    method limit_to_first (line 43) | pub fn limit_to_first(&mut self, count: u32) -> &mut Params {
    method limit_to_last (line 47) | pub fn limit_to_last(&mut self, count: u32) -> &mut Params {
    method start_at (line 51) | pub fn start_at(&mut self, index: u32) -> &mut Params {
    method end_at (line 55) | pub fn end_at(&mut self, index: u32) -> &mut Params {
    method equal_to (line 59) | pub fn equal_to(&mut self, value: u32) -> &mut Params {
    method shallow (line 63) | pub fn shallow(&mut self, flag: bool) -> &mut Params {
    method format (line 67) | pub fn format(&mut self) -> &mut Params {
    method finish (line 71) | pub fn finish(&self) -> Firebase {
  function check_params (line 83) | fn check_params() {

FILE: src/sse.rs
  type ServerEvents (line 4) | pub struct ServerEvents {
    method new (line 9) | pub fn new(url: &str) -> Option<Self> {
    method listen (line 20) | pub async fn listen(
    method stream (line 37) | pub fn stream(

FILE: src/utils.rs
  function check_uri (line 5) | pub fn check_uri(uri: &str) -> UrlParseResult<Url> {
Condensed preview — 11 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (27K chars).
[
  {
    "path": ".cargo/config",
    "chars": 36,
    "preview": "[alias]\r\nt = \"test -- --nocapture\"\r\n"
  },
  {
    "path": ".gitignore",
    "chars": 14,
    "preview": "/target\r\n.idea"
  },
  {
    "path": "Cargo.toml",
    "chars": 774,
    "preview": "[package]\r\nname = \"firebase-rs\"\r\nedition = \"2021\"\r\nversion = \"2.2.5\"\r\ndescription = \"Rust based Firebase library\"\r\nreadm"
  },
  {
    "path": "LICENSE",
    "chars": 1089,
    "preview": "MIT License\r\n\r\nCopyright (c) 2020 Emre YALVAÇ\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a"
  },
  {
    "path": "README.md",
    "chars": 3655,
    "preview": "# firebase-rs\n\n[![Crates.io](https://img.shields.io/crates/v/firebase-rs.svg)](https://crates.io/crates/firebase-rs) [!["
  },
  {
    "path": "src/constants.rs",
    "chars": 660,
    "preview": "pub const AUTH: &str = \"auth\";\npub const ORDER_BY: &str = \"orderBy\";\npub const LIMIT_TO_FIRST: &str = \"limitToFirst\";\npu"
  },
  {
    "path": "src/errors.rs",
    "chars": 2021,
    "preview": "use std::{\n    error::Error,\n    fmt::{Display, Formatter},\n};\n\npub type UrlParseResult<T> = Result<T, UrlParseError>;\n\n"
  },
  {
    "path": "src/lib.rs",
    "chars": 11838,
    "preview": "use constants::{Method, Response, AUTH};\nuse errors::{RequestResult, UrlParseResult};\nuse params::Params;\nuse reqwest::S"
  },
  {
    "path": "src/params.rs",
    "chars": 2448,
    "preview": "use crate::constants::{\n    END_AT, EQUAL_TO, EXPORT, FORMAT, LIMIT_TO_FIRST, LIMIT_TO_LAST, ORDER_BY, SHALLOW, START_AT"
  },
  {
    "path": "src/sse.rs",
    "chars": 2012,
    "preview": "use eventsource_client::*;\r\nuse futures_util::StreamExt;\r\n\r\npub struct ServerEvents {\r\n    client: ClientBuilder,\r\n}\r\n\r\n"
  },
  {
    "path": "src/utils.rs",
    "chars": 378,
    "preview": "use crate::errors::UrlParseResult;\nuse crate::UrlParseError;\nuse url::Url;\n\npub fn check_uri(uri: &str) -> UrlParseResul"
  }
]

About this extraction

This page contains the full source code of the emreyalvac/firebase-rs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 11 files (24.3 KB), approximately 6.3k tokens, and a symbol index with 63 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!