MCPcopy Index your code
hub / github.com/Alorel/rust-indexed-db

github.com/Alorel/rust-indexed-db @v0.6.4

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.6.4 ↗ · + Follow
644 symbols 1,624 edges 123 files 26 documented · 4%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Wraps the web_sys Indexed DB API in a Future-based API and removes the pain of dealing with JS callbacks or JSValue in Rust.

master CI badge crates.io badge docs.rs badge dependencies badge

Goals & features:

  • Shield you from having to interact with web_sys or js_sys APIs - this should feel like a native Rust API.
  • Integrate with serde, but don't require it - as a rule of thumb, you'll use serde-serialisable types when working with JS objects & bypass serde for Javascript primitives.
  • Implement Stream where applicable - cursors and key cursors have this at the time of writing.
  • Implement a more Rust-oriented API - for example, transactions will roll back by default unless explicitly committed to allow you to use ?s.
use indexed_db_futures::database::Database;
use indexed_db_futures::prelude::*;
use indexed_db_futures::transaction::TransactionMode;

#[derive(Serialize, Deserialize)]
struct MySerdeType(u8, String);

#[derive(Deserialize)]
#[serde(untagged)]
enum ObjectOrString {
    Object(MySerdeType),
    String(String),
}

async fn main() -> indexed_db_futures::OpenDbResult<()> {
    let db = Database::open("my_db")
        .with_version(2u8)
        .with_on_upgrade_needed(|event, db| {
            // Convert versions from floats to integers to allow using them in match expressions
            let old_version = event.old_version() as u64;
            let new_version = event.new_version().map(|v| v as u64);

            match (event.old_version(), event.new_version()) {
                (0, Some(1)) => {
                    db.create_object_store("my_store")
                        .with_auto_increment(true)
                        .build()?;
                }
                (prev, Some(2)) => {
                    if prev == 1 {
                        let _ = db.delete_object_store("my_store");
                    }

                    db.create_object_store("my_other_store").build()?;
                }
                _ => {}
            }

            Ok(())
        })
        .await?;

    // Populate some data
    let transaction = db
        .transaction("my_other_store")
        .with_mode(TransactionMode::Readwrite)
        .build()?;

    let store = transaction.object_store("my_other_store")?;

    store
        .put("a primitive value that doesn't need serde")
        .with_key("my_key")
        .await?;

    // Awaiting individual requests is optional - they still go out
    store
        .put(MySerdeType(10, "foos".into()))
        .with_key("my_serde_key")
        .with_key_type::<String>() // `serde` keys must be deserialisable; String is, but the &str above isn't
        .serde()?;

    // Unlike JS, transactions ROLL BACK INSTEAD OF COMMITTING BY DEFAULT
    transaction.commit().await?;

    // Read some data
    let transaction = db.transaction("my_other_store").build()?;
    let store = transaction.object_store("my_other_store")?;

    // `None` is returned if the cursor is empty
    if let Some(mut cursor) = store.open_cursor().await? {
        // Use a limited loop in case we made a mistake and result in an infinite loop
        for _ in 0..5 {
            // We inserted a serde record and a primitive one so we need to deserialise as an enum that supports both
            match cursor.next_record_ser::<ObjectOrString>().await {
                Ok(Some(record)) => match record {
                    ObjectOrString::Object(serde_record) => {
                        assert_eq!(serde_record.0, 10);
                        assert_eq!(serde_record.1, "foos");
                    }
                    ObjectOrString::String(string_record) => {
                        assert_eq!(
                            string_record.as_str(),
                            "a primitive value that doesn't need serde"
                        );
                    }
                },
                Err(e) => return Err(e.into()),
                Ok(None) => return Ok(()), // reached cursor end
            }
        }

        panic!("Got an infinite loop!");
    }

    Ok(())
}

Head over to the docs for a proper introduction!

Extension points exported contracts — how you extend this code

TryFromJs (Interface)
Convert from a JS value. [16 implementers]
src/primitive/from_js.rs
SerialiseToJs (Interface)
A type that's convertible to [`JsValue`] using `serde`, but not necessarily [`serialisable`](serde::Serialize) as a whol [5 …
src/serde.rs
Build (Interface)
(no doc) [22 implementers]
src/build.rs
SystemRepr (Interface)
(no doc) [14 implementers]
src/internal_utils.rs
ObjectStoreName (Interface)
(no doc) [6 implementers]
src/database/store_name.rs
PollUnpinned (Interface)
(no doc) [16 implementers]
src/future/traits.rs
BuildDyn (Interface)
Build with `serde` if the feature's enabled, else build with `primitive`. [1 implementers]
tests/tests/utils/conditional_build.rs
DBVersion (Interface)
(no doc) [2 implementers]
src/factory/db_version.rs

Core symbols most depended-on inside this repo

as_sys
called by 46
src/future/basic.rs
build
called by 44
src/build.rs
create_object_store
called by 26
src/database.rs
try_to_js
called by 18
src/primitive/try_to_js.rs
transaction
called by 17
src/database.rs
clone
called by 16
src/typed_array.rs
into_iter
called by 15
src/typed_array.rs
with_on_upgrade_needed
called by 15
src/factory/req_builder.rs

Shape

Method 397
Function 126
Class 72
Enum 25
Interface 24

Languages

Rust100%

Modules by API surface

src/cursor/base_cursor.rs23 symbols
src/future/open_db/listener.rs18 symbols
tests/tests/object_store/query_source/cursor.rs17 symbols
src/database.rs17 symbols
src/cursor.rs16 symbols
src/object_store/add_put.rs14 symbols
src/future/open_db.rs14 symbols
src/query_source/get_all.rs13 symbols
src/query_source/cursor.rs13 symbols
src/object_store.rs13 symbols
tests/tests/index/query_source/cursor.rs12 symbols
src/typed_array.rs12 symbols

For agents

$ claude mcp add rust-indexed-db \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page