RippleDB
RippleDB
Adapters

db-memory

In-memory adapter for testing

@rippledb/db-memory

A simple in-memory adapter for unit testing. No persistence, no dependencies.

Not for production. Data is lost when the process exits.

Installation

pnpm add @rippledb/db-memory
npm install @rippledb/db-memory
yarn add @rippledb/db-memory

Usage

import { MemoryDb } from "@rippledb/db-memory";

const db = new MemoryDb<MySchema>();

// Append changes
await db.append({
  stream: "test-stream",
  changes: [
    {
      entity: "todos",
      entityId: "todo-1",
      kind: "upsert",
      patch: { title: "Test" },
      tags: { title: hlc() },
      hlc: hlc(),
    },
  ],
});

// Pull changes
const { changes, nextCursor } = await db.pull({
  stream: "test-stream",
  cursor: null,
});

Features

  • Zero config: No database setup required
  • Fast: Pure JavaScript, no I/O
  • Isolated: Each instance has its own state
  • Full Db interface: Supports append, pull, idempotency

Limitations

  • No materialization: Only stores the change log
  • No persistence: Data lives only in memory
  • Single process: Can't share state between processes

Testing Example

import { describe, it, expect, beforeEach } from "vitest";
import { MemoryDb } from "@rippledb/db-memory";
import { makeUpsert } from "@rippledb/core";

describe("TodoService", () => {
  let db: MemoryDb<MySchema>;

  beforeEach(() => {
    db = new MemoryDb();
  });

  it("creates a todo", async () => {
    await db.append({
      stream: "user-123",
      changes: [
        makeUpsert({
          stream: "user-123",
          entity: "todos",
          entityId: "todo-1",
          patch: { id: "todo-1", title: "Test", done: false },
          hlc: "1000:0:test",
        }),
      ],
    });

    const { changes } = await db.pull({ stream: "user-123", cursor: null });
    expect(changes).toHaveLength(1);
    expect(changes[0].patch.title).toBe("Test");
  });

  it("supports idempotency", async () => {
    const change = makeUpsert({
      stream: "user-123",
      entity: "todos",
      entityId: "todo-1",
      patch: { id: "todo-1", title: "Test", done: false },
      hlc: "1000:0:test",
    });

    // First append succeeds
    const result1 = await db.append({
      stream: "user-123",
      changes: [change],
      idempotencyKey: "key-1",
    });
    expect(result1.accepted).toBe(1);

    // Second append with same key is ignored
    const result2 = await db.append({
      stream: "user-123",
      changes: [change],
      idempotencyKey: "key-1",
    });
    expect(result2.accepted).toBe(0);
  });
});

When to Use

ScenarioRecommendation
Unit testsdb-memory
Integration testsdb-sqlite with :memory:
E2E testsReal database adapter
Developmentdb-sqlite or db-turso

On this page