#indexed-db #idb #macro-derive #future #object-store

deli-derive

为在浏览器中使用 derive 宏轻松创建和管理 indexed db 中的对象存储,对 idb 创建的便利包装

1 个不稳定版本

0.1.0 2022年11月23日

#6#idb


用于 deli

MIT/Apache

27KB
457

deli

Deli 是对 idb 创建的便利包装,用于在浏览器中使用 derive 宏轻松创建和管理 indexed db 中的对象存储。

用法

要使用 deli,您需要在您的 Cargo.toml 中添加以下内容

[dependencies]
deli = "0.1"

deli 旨在用于使用 webassembly 的浏览器。因此,请确保使用 --target wasm32-unknown-unknown 编译您的项目。或者,您可以在您的 .cargo/config.toml 中添加以下构建配置

[build]
target = "wasm32-unknown-unknown"

示例

定义一个 Model

第一步是使用 Model derive 宏定义您的数据模型。您还需要为您的模型实现 serde::Serializeserde::Deserialize trait,以便在将其保存到存储之前将数据转换为 json

use deli::Model;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Model)]
pub struct Employee {
    #[deli(auto_increment)]
    pub id: u32,
    pub name: String,
    #[deli(unique)]
    pub email: String,
    #[deli(index)]
    pub age: u8,
}

Model derive 宏会自动为您 struct 实现 Model trait 并创建一个 Store,用于访问和写入存储中的数据。

容器属性
  • #[deli(name)]:在索引数据库中,默认情况下,在创建数据库时会创建一个名为结构体名称的新对象存储(在上面的例子中,它将在索引数据库中创建一个名为Employee的对象存储)。要更改默认对象存储名称,请使用#[deli(name = "your_object_store_name")]

  • #[deli(store_name)]:默认情况下,派生宏将创建一个名为<ModelName>Store的结构体(在上面的例子中,它将创建一个EmployeeStore结构体)。要更改默认名称,请使用#[deli(store_name = "YourStoreName")]

字段属性
  • #[deli(key)]:定义对象存储的主键路径。
  • #[deli(auto_increment)]:定义具有auto_increment值的对象存储的主键路径(意味着#[deli(key)])。
  • #[deli(index)]:为字段创建索引。
  • #[deli(unique)]:为字段创建唯一索引(意味着#[deli(index)])。
  • #[deli(multi_entry)]:为字段创建一个多入口索引(隐含#[deli(index)])。
  • #[deli(rename)]:重命名对象存储中的字段。注意,这应与serde序列化保持一致。例如,如果您使用#[serde(rename_all = "camelCase")],您需要适当地重命名deli字段以与serde序列化保持同步。

创建数据库

下一步是创建一个新的Database实例,并将其与模型注册。

use deli::{Database, Error};

async fn create_database() -> Result<Database, Error> {
    let database = Database.builder("test_db", 1).register_model::<Employee>().await?;
}

开始事务

一旦创建了Database实例,您就可以使用事务开始读取和写入数据库数据。

use deli::{Database, Error, Transaction};

fn create_read_transaction(database: &Database) -> Result<Transaction, Error> {
    database.transaction().with_model::<Employee>().build()
}

fn create_write_transaction(database: &Database) -> Result<Transaction, Error> {
    database.transaction().writable().with_model::<Employee>().build()
}

您可以通过添加多个.with_model::<Model>()调用,将多个模型添加到事务中。

读取和写入模型存储数据

一旦您有了模型的交易,您就可以读取或写入该模型的数据。

use deli::{Error, Model, Transaction};

async fn add_employee(transaction: &Transaction) -> Result<u32, Error> {
    Employee::with_transaction(transaction)?.add("Alice", "[email protected]", &25).await
}

async fn get_employee(transaction: &Transaction, id: u32) -> Result<Option<Employee>, Error> {
    Employee::with_transaction(transaction)?.get(&id).await
}

async fn get_all_employees(transaction: &Transaction) -> Result<Vec<Employee>, Error> {
    // NOTE: Here `..` (i.e., `RangeFull`) means fetch all values from store
    Employee::with_transaction(transaction)?.get_all(.., None).await
}

async fn get_employees_with_bounds(
    transaction: &Transaction,
    from_id: u32,
    to_id: u32,
) -> Result<Vec<Employee>, Error> {
    Employee::with_transaction(transaction)?.get_all(&from_id..=&to_id, None).await
}

提交事务

完成所有写入后,您可以提交事务

async fn commit_transaction(transaction: Transaction) -> Result<(), Error> {
    transaction.commit().await
}

请注意,commit()通常不需要调用——当所有未解决的请求得到满足且没有新的请求时,事务会自动提交。

此外,当使用长生命周期的索引数据库事务时,请注意其行为可能会根据浏览器而改变。例如,在事件循环中进行IO(网络请求)时,事务可能会自动提交。

许可证

根据您的选择,许可协议为

自由选择。

贡献

除非您明确声明,否则根据Apache-2.0许可证定义的您有意提交以包含在工作中的任何贡献,应按上述方式双许可,无需附加条款或条件。

依赖关系

~2MB
~42K SLoC