Files
PotentialStorage/test
Claude 7d755cecae
CI / Node 22 (push) Successful in 13s
CI / Node 24 (push) Successful in 13s
CI / Node 26 (push) Successful in 14s
CI / Node 24 (pull_request) Successful in 12s
CI / Chromium (pull_request) Successful in 48s
CI / Publish to staging registry (pull_request) Skipped
CI / Node 22 (pull_request) Successful in 13s
CI / Node 26 (pull_request) Successful in 12s
CI / Chromium (push) Successful in 47s
CI / Publish to staging registry (push) Successful in 10s
Signed requests: strictly increasing timestamps per key
Ed25519 signatures are deterministic, so two identical requests from one key in the same
millisecond (e.g. two devices subscribing to the same path, or parallel identical reads)
had the same signature, and the server rejected the second as a replay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qxbkp4tA7G5SCWjzWuxmE
2026-10-23 14:36:25 +00:00
..

import { afterEach, describe, expect, it } from 'vitest'
import {
  DocumentStorageKV,
  Ed25519Signer,
  Ed25519Verifier,
  EventStorageKV,
  KVStorageComposite,
  KVStorageEncrypted,
  KVStorageHttp,
  KVStorageHttpServer,
  KVStorageInMemory,
  type Fields,
  type Many,
} from '../src/index.js'
import { collect } from './helpers.js'

// The README's examples, run as written (imports from the package entry point), so they stay correct.

const closers: (() => Promise<void>)[] = []
afterEach(async () => {
  for (const close of closers.splice(0)) await close()
})

describe('README', () => {
  it('KV storage', async () => {
    const db = new KVStorageInMemory()
    const users = db.child('users')
    await users.set('1', { name: 'Ada' })
    expect(await users.child('1').get()).toEqual({ name: 'Ada' })
    expect(await users.get('1')).toEqual({ name: 'Ada' })
    await users.setMany([
      ['2', { name: 'Bob' }],
      ['3', { name: 'Cy' }],
    ])
    expect(await users.getMany(['1', 'missing'])).toEqual([{ name: 'Ada' }, undefined])
    expect(await collect(users.keys({ limit: 10 }))).toEqual(['1', '2', '3'])
    expect((await collect(users.entries({ reverse: true }))).map(([key]) => key)).toEqual(['3', '2', '1'])
    await users.delete('3')
    await users.deleteTree()
    expect(await collect(db.scan())).toEqual([])

    const settings = db.child('settings')
    await settings.setFields({ theme: 'dark', fontSize: 14 })
    expect(await settings.get('theme')).toBe('dark')
    expect(await settings.getFields()).toEqual({ fontSize: 14, theme: 'dark' })

    const changes: unknown[] = []
    db.on('change', ({ changes: c, origin }) => changes.push([origin, c]))
    await users.set('1', { name: 'Ada' })
    expect(changes).toEqual([['local', [{ key: 'users/1', value: { name: 'Ada' } }]]])
  })

  it('types', async () => {
    type User = { name: string }
    type Schema = { children: { users: Many<User>; settings: { children: Fields<{ theme: string; fontSize: number }> } } }
    const typed = new KVStorageInMemory<Schema>()
    await typed.child('users').set('1', { name: 'Ada' })
    // @ts-expect-error not a User
    await typed.child('users').set('2', { nom: 'x' })
    await typed.child('settings').set('theme', 'dark')
    const theme: string | undefined = await typed.child('settings').get('theme')
    expect(theme).toBe('dark')
  })

  it('event storage', async () => {
    const events = new EventStorageKV(new KVStorageInMemory())
    const orders = events.child('orders')
    const [id] = await orders.append('o1', [{ type: 'created', total: 30 }])
    await orders.child('o1').append([{ type: 'paid' }])
    expect((await collect(orders.read('o1'))).map((e) => e.data)).toEqual([{ type: 'created', total: 30 }, { type: 'paid' }])
    expect((await collect(orders.read('o1', { after: id }))).map((e) => e.data)).toEqual([{ type: 'paid' }])
    expect(await collect(orders.keys())).toEqual(['o1'])
  })

  it('document storage', async () => {
    const docs = new DocumentStorageKV(new KVStorageInMemory())
    const people = docs.child('people')
    const id = await people.insert({ name: 'Ada', age: 36, tags: ['math'] })
    await people.set('grace', { name: 'Grace', age: 45, tags: ['navy', 'cobol'] })
    await people.update(id, { $inc: { age: 1 }, $push: { tags: 'engines' } })
    expect((await collect(people.find({ age: { $gte: 37 } }, { sort: { age: -1 }, limit: 10 }))).map((r) => r.key)).toEqual(['grace', id])
    expect((await people.findOne({ tags: 'cobol' }))?.key).toBe('grace')
    expect(await people.get(id)).toEqual({ name: 'Ada', age: 37, tags: ['math', 'engines'] })
    expect(await people.delete('grace')).toBe(true)
  })

  it('sync, offline and encryption (server and client)', async () => {
    const server = new KVStorageHttpServer(new KVStorageInMemory(), {
      auth: { verifiers: [new Ed25519Verifier()] },
      basePath: '/kv',
      allowOrigins: ['https://app.example.com'],
    })
    const fetch = (url: string, init: RequestInit) => server.handle(new Request(url, init))

    const signer = await Ed25519Signer.generate()
    const saved = await signer.exportPrivateKey()
    expect((await Ed25519Signer.fromPrivateKey(saved)).publicKey).toBe(signer.publicKey)
    const salt = crypto.getRandomValues(new Uint8Array(16))
    const key = await KVStorageEncrypted.deriveKey('correct horse battery staple', salt, 1000)

    const local = new KVStorageInMemory() // stands in for KVStorageIndexedDB
    const db = new KVStorageComposite({
      source: new KVStorageEncrypted(new KVStorageHttp({ url: 'https://api.example.com/kv', signer, fetch }), { key }),
      replicas: [new KVStorageInMemory(), local],
      queue: local.child('~sync'),
      prefix: signer.publicKey,
    })
    closers.push(() => db.close())

    const me = db.child(signer.publicKey)
    await me.child('notes').set('1', { text: 'Works offline' })
    expect(await me.child('notes').get('1')).toEqual({ text: 'Works offline' })

    type Todo = { title: string; done: boolean }
    const todos = new DocumentStorageKV<{ children: { todos: Many<Todo> } }>(me).child('todos')
    await todos.insert({ title: 'Ship it', done: false })
    expect((await collect(todos.find({ done: false }))).map((r) => r.data.title)).toEqual(['Ship it'])

    // Another device with the same keys sees the data; the server only has ciphertext.
    const other = new KVStorageComposite({
      source: new KVStorageEncrypted(new KVStorageHttp({ url: 'https://api.example.com/kv', signer, fetch }), { key }),
      replicas: [new KVStorageInMemory()],
      prefix: signer.publicKey,
    })
    closers.push(() => other.close())
    expect(await other.child(signer.publicKey).child('notes').get('1')).toEqual({ text: 'Works offline' })

    const http = new KVStorageHttp({ url: 'https://api.example.com/kv', signer, fetch })
    closers.push(() => http.close())
    const [stored] = await http.readMany([`${signer.publicKey}/notes/1`])
    expect(stored).toBeInstanceOf(Uint8Array)
    const pushed = http.waitFor('change', () => true)
    await http.child(signer.publicKey).child('notes').subscribe()
    await me.child('notes').set('2', { text: 'live' })
    expect((await pushed).changes[0]!.key).toBe(`${signer.publicKey}/notes/2`)
  })
})