Skip to content

Expressing interest in Repo.import and Repo.delete #60

Description

@matta

Repo.import

Use case: I've got a local first app that allows the user to export the automerge file for backup purposes. Doing so doesn't change the doc's ID, so I embed that ID in the doc itself. If the user ever imports the doc, ideally it has the same ID. The automerge-repo impl provides Repo.import, which allows the doc ID to be specified, solving the problem nicely.

Using samod, I resorted to a hack that amounts to writing to IndexDB directly with a "samod-compatible" file name and contents. See code below, which uses my own SamodStorage IndexDB impl.

See https://automerge.org/automerge-repo/classes/_automerge_automerge-repo.Repo.html#import

Repo.delete

Use case: in a local first app it seems like a good idea to allow the user to delete their data. :-)

See https://automerge.org/automerge-repo/classes/_automerge_automerge-repo.Repo.html#delete

P.S. here is the code for my "hack"

    /// Explicitly inject a document into the underlying WASM storage with a known ID.
    /// This bypasses `repo.create()` which forces a new random ID.
    #[cfg(target_arch = "wasm32")]
    async fn inject_existing_doc(
        repo: samod::Repo,
        id: DocumentId,
        doc: &automerge::Automerge,
    ) -> Result<(samod::DocHandle, DocumentId)> {
        // This code is a hack to work around the fact that we can't create a
        // document with a known ID. TODO: Remove this hack if Samod ever
        // has a Repo.inject facility.
        //
        // The problem is that `repo.create()` always generates a new random ID,
        // but we need to create a document with a specific ID (the one passed
        // in as an argument).
        //
        // The solution is to manually inject the document into storage and then
        // find it via `repo.find()`.
        
        use crate::samod_storage::SamodStorage;
        use samod::storage::{LocalStorage, StorageKey};

        let hash = samod_core::CompactionHash::new(&doc.get_heads());
        let samod_id: samod::DocumentId = id.into();
        let key = StorageKey::snapshot_path(&samod_id, &hash);

        // Manually inject into storage to bypass Repo::create generating a new ID
        let storage = SamodStorage::new("tasklens_samod", "documents");
        storage.put(key, doc.save()).await;

        // Now find it via Repo (which should look in storage)
        match Self::find_doc(repo, id).await {
            Ok(Some(handle)) => Ok((handle, id)),
            Ok(None) => Err(anyhow!(
                "Document {} not found after manual storage injection",
                id
            )),
            Err(e) => Err(anyhow!(
                "Error finding document {} after manual injection: {:?}",
                id,
                e
            )),
        }
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions