#firebase #firestore #grpc #gcp

firestore_grpc

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

146 breaking releases

new 0.203.0 Feb 18, 2024
0.201.0 Feb 4, 2024
0.196.0 Dec 31, 2023
0.191.0 Nov 26, 2023
0.1.1 Mar 11, 2020

#1 in #api-definition

Download history 147/week @ 2023-11-02 168/week @ 2023-11-09 134/week @ 2023-11-16 310/week @ 2023-11-23 746/week @ 2023-11-30 223/week @ 2023-12-07 279/week @ 2023-12-14 374/week @ 2023-12-21 264/week @ 2023-12-28 150/week @ 2024-01-04 203/week @ 2024-01-11 257/week @ 2024-01-18 388/week @ 2024-01-25 409/week @ 2024-02-01 293/week @ 2024-02-08 1373/week @ 2024-02-15

2,526 downloads per month
Used in 4 crates

MIT license

6MB
4.5K SLoC

Prolog 4.5K SLoC Rust 28 SLoC Shell 6 SLoC

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

~13–25MB
~438K SLoC