#firestore #grpc-client #grpc #firebase #gcp #google-api #api-client

firestore_grpc

A gRPC client library for Firestore, generated automatically from the API definition files in Google APIs

187 breaking releases

new 0.244.0 Dec 1, 2024
0.243.0 Nov 24, 2024
0.242.0 Nov 17, 2024
0.226.0 Jul 28, 2024
0.1.1 Mar 11, 2020

#878 in Web programming

Download history 176/week @ 2024-08-10 223/week @ 2024-08-17 246/week @ 2024-08-24 303/week @ 2024-08-31 288/week @ 2024-09-07 347/week @ 2024-09-14 357/week @ 2024-09-21 279/week @ 2024-09-28 257/week @ 2024-10-05 367/week @ 2024-10-12 249/week @ 2024-10-19 218/week @ 2024-10-26 300/week @ 2024-11-02 289/week @ 2024-11-09 194/week @ 2024-11-16 210/week @ 2024-11-23

1,024 downloads per month
Used in 4 crates

MIT license

7.5MB

firestore-grpc

Firestore client library for Rust. If you use Cloud Run, please use https://github.com/gkkachi/firestore-grpc-cloudrun instead, which provides some useful functions such as get_client(), get_project_id().

Example

This example is experimental. In a real situation, you need to implement features such as token updates.

Environment variables

export PROJECT_ID=YOUR_PROJECT_ID
export TOKEN=`gcloud auth print-access-token`

Code

Cargo.toml

[dependencies]
firestore_grpc = "0.109"
tokio = {version = "1.0", features = ["full"]}

main.rs

use firestore_grpc::tonic::{
    codegen::InterceptedService,
    metadata::MetadataValue,
    transport::{Channel, ClientTlsConfig},
    Request, Status,
};
use firestore_grpc::v1::{
    firestore_client::FirestoreClient, value::ValueType, CreateDocumentRequest, Document, Value,
};
use std::env;

const URL: &'static str = "https://firestore.googleapis.com";
const DOMAIN: &'static str = "firestore.googleapis.com";

pub type BoxError = Box<dyn std::error::Error + Sync + Send + 'static>;

fn get_token() -> String {
    env::var("TOKEN").unwrap()
}

fn get_project_id() -> String {
    env::var("PROJECT_ID").unwrap()
}

async fn get_client() -> Result<FirestoreClient<InterceptedService<Channel, impl Fn(Request<()>) -> Result<Request<()>, Status>>>, BoxError> {
    let endpoint = Channel::from_static(URL).tls_config(ClientTlsConfig::new().domain_name(DOMAIN));

    let bearer_token = format!("Bearer {}", get_token());
    let header_value = MetadataValue::from_str(&bearer_token)?;

    let channel = endpoint?.connect().await?;

    let service = FirestoreClient::with_interceptor(channel, move |mut req: Request<()>| {
        req.metadata_mut()
            .insert("authorization", header_value.clone());
        Ok(req)
    });
    Ok(service)
}

async fn create_document() -> Result<Document, BoxError> {
    let parent = format!(
        "projects/{}/databases/(default)/documents",
        get_project_id()
    );
    let collection_id = "greetings".into();
    let document_id = "".into();
    let mut fields = std::collections::HashMap::new();
    fields.insert(
        "message".into(),
        Value {
            value_type: Some(ValueType::StringValue("Hello world!".into())),
        },
    );
    let document = Some(Document {
        name: "".into(),
        fields,
        create_time: None,
        update_time: None,
    });
    let res = get_client()
        .await?
        .create_document(CreateDocumentRequest {
            parent,
            collection_id,
            document_id,
            document,
            mask: None,
        })
        .await?;
    Ok(res.into_inner())
}

#[tokio::main]
async fn main() {
    create_document().await.unwrap();
}

Dependencies

~14–24MB
~450K SLoC