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

firestore_grpc

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

155 breaking releases

new 0.212.0 Apr 21, 2024
0.210.0 Apr 7, 2024
0.209.0 Mar 31, 2024
0.196.0 Dec 31, 2023
0.1.1 Mar 11, 2020

#9 in #firebase

Download history 7/week @ 2023-12-24 24/week @ 2023-12-31 47/week @ 2024-01-07 77/week @ 2024-01-14 36/week @ 2024-01-21 29/week @ 2024-01-28 45/week @ 2024-02-04 43/week @ 2024-02-11 518/week @ 2024-02-18 513/week @ 2024-02-25 238/week @ 2024-03-03 463/week @ 2024-03-10 280/week @ 2024-03-17 272/week @ 2024-03-24 557/week @ 2024-03-31 230/week @ 2024-04-07

1,420 downloads per month
Used in 4 crates

MIT license

6.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

~12–25MB
~425K SLoC