Fireproof Database API Guide

website·Indexed 33 days ago

https://use-fireproof.com/

A lightweight embedded document database with encrypted live sync designed for browser applications.

Tokens
1.7K
Snippets
11
Records
11
Agent score
19%

What's inside Fireproof

  1. Manage file attachments in Fireproof

    Fireproof supports encrypted, on-demand synced file attachments. To attach files to a document, add them to the _files property of the document object. When retrieving a document, the _files property contains metadata; call the .file() method on the attachment metadata to retrieve the actual File object as a Promise.
    // Saving files
    function handleFiles(event) {
      const fileList = event.target.files;
      const doc = {
        type: "files",
        _files: {}
      };
      for (const file of fileList) {
        doc._files[file.name] = file; 
      }
      database.put(doc);
    }
    
    // Retrieving files
    const doc = await database.get("my-doc-id");
    for (const fileName in doc._files) {
      const meta = doc._files[fileName];
      if (meta.file) {
        const fileObj = await meta.file();
        console.log("Loaded file:", fileObj.name);
      }
    }
  2. Create sortable lists with midpoint positioning

    To implement a sortable list, use a numeric position field and a composite index containing the list ID and the position. New items can be inserted between existing items by calculating the midpoint of the surrounding documents' positions.
    const { database, useLiveQuery } = useFireproof("my-ledger");
    
    // Query items on list 'xyz' sorted by position
    const queryResult = useLiveQuery(
      (doc) => [doc.list, doc.position], 
      { prefix: ["xyz"] }
    );
    
    async function insertBetween(beforeDoc, afterDoc) {
      const newPosition = (beforeDoc.position + afterDoc.position) / 2;
      await database.put({ 
        list: "xyz", 
        position: newPosition 
      });
    }
  3. Use Fireproof in React with useFireproof

    The useFireproof hook provides a suite of tools for React integration, including useLiveQuery for real-time data fetching and useDocument for managing document state.

    Critical State Management Rule: Do not use useState() for form data that will be persisted. Instead, use merge() to update the local draft and submit() to persist the document to the database. Use useState only for ephemeral UI state (e.g., active tabs, open panels).

    import { useFireproof } from "use-fireproof";
    
    export default function App() {
      const { useLiveQuery, useDocument, database } = useFireproof("todo-list-db");
    
      // Manage a document draft
      const { 
        doc: newTodo, 
        merge: mergeNewTodo, 
        submit: submitNewTodo 
      } = useDocument({
        todo: "",
        type: "todo",
        completed: false,
        createdAt: Date.now()
      });
    
      // Query data in real-time
      const { docs: todos } = useLiveQuery("type", { 
        key: "todo",
        descending: true 
      });
    
      const handleInputChange = (e) => {
        mergeNewTodo({ todo: e.target.value });
      };
    
      const handleSubmit = (e) => {
        e.preventDefault();
        submitNewTodo();
      };
    
      return (
        // ... JSX using newTodo.todo and todos.map()
      );
    }
  4. Subscribe to database changes

    Use the database.subscribe method to listen for real-time changes in the Fireproof database. The callback receives an array of changes, allowing you to trigger side effects (such as sending emails or updating UI) when specific data conditions are met.
    import { fireproof } from "use-firproof";
    
    const database = fireproof("todo-list-db");
    
    database.subscribe((changes) => {
      console.log("Recent changes:", changes);
      changes.forEach((change) => {
        if (change.completed) {
          sendEmail(change.email, "Todo completed", "You have completed a todo.");
        }
      });
    }, true);
  5. Query data using useLiveQuery

    useLiveQuery provides real-time updates for documents based on sorted indexes.

    • Temporal Sorting: Use _id to get documents sorted by time.
    • Key Filtering: Pass a field name and a key to filter for specific values.
    • Range Queries: Use the range option (an array of two values) to filter numeric or sortable data.
    • Prefix Queries: Use an array index and the prefix option to group records (e.g., by date).
    // 1. Temporal sorting (most recent first)
    const { docs } = useLiveQuery("_id", { descending: true, limit: 100 });
    
    // 2. Filter by specific key
    const { docs } = useLiveQuery("agentName", { key: "agent-1" });
    
    // 3. Range query
    const { docs } = useLiveQuery("agentRating", { range: [3, 5] });
    
    // 4. Prefix query for grouping (e.g., November 2024)
    const queryResult = useLiveQuery(
      (doc) => [doc.date.getFullYear(), doc.date.getMonth(), doc.date.getDate()],
      { prefix: [2024, 11] }
    );
  6. Use Fireproof Core API in non-React environments

    For use in vanilla JavaScript, HTML, or backend environments (Node.js, Deno, Bun), use the fireproof core API instead of hooks. The core API is asynchronous.
    import { fireproof } from "use-fireproof";
    
    const database = fireproof("my-ledger");
    
    // Put a document
    const ok = await database.put({ text: "Sample Data" });
    
    // Get a document by ID
    const doc = await database.get(ok.id);
    
    // Query documents
    const latest = await database.query("_id", { limit: 10, descending: true });
    console.log("Latest documents:", latest.docs);
  7. Implement custom indexes and data normalization

    You can pass a function to useLiveQuery to create a custom index. This is useful for normalizing legacy data types or creating complex sort keys. The index function is sandboxed and cannot access external variables.
    const { docs } = useLiveQuery(
      (doc) => {
        if (doc.type == 'listing_v1') {
          return doc.sellerId;
        } else if (doc.type == 'listing') {
          return doc.userId;
        }
      }, 
      { key : routeParams.sellerId }
    );
  8. Manage documents with useDocument hook

    The useDocument hook allows you to create, edit, and save JSON-style documents. Documents use an _id field; if not provided, one is auto-generated to avoid conflicts.

    Available methods:

    • merge(updates): Updates the document with new fields.
    • submit(e): Prevents default form behavior, saves the document, and resets it to the initial state.
    • save(): Persists the current document state.
    • reset(): Resets the document to its initial state.
    const { useDocument } = useFireproof("my-ledger");
    
    // For a specific resource (e.g., user profile)
    const { doc, merge, submit, save, reset } = useDocument({ _id: "user-profile:abc@example.com" });
    
    // For a new document
    const { doc, merge, submit } = useDocument({ text: "" });
  9. Display images from Fireproof using ImgFile

    When using the use-fireproof library in React, use the ImgFile component to render images stored in the _files property of a document.
    import { ImgFile } from "use-fireproof";
    
    // Inside a map of documents
    {doc._files?.uploaded && (
      <ImgFile 
        file={doc._files.uploaded} 
        alt="Uploaded Image" 
        className="w-full h-auto rounded" 
      />
    )}
    
  10. Initialize a Fireproof Database in React

    Use the useFireproof hook to create or load a database. Databases are identified by a string name and serve as the unit of sharing for collaboration sessions. The hook returns the database instance and specialized hooks for querying and document management.
    import { useFireproof } from "use-fireproof";
    
    const { database, useLiveQuery, useDocument } = useFireproof("my-ledger");