JSPM

@mdxdb/sqlite

1.9.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 14
  • Score
    100M100P100Q45800F
  • License MIT

Cloudflare Durable Objects SQLite adapter for mdxdb - namespace-isolated storage with Workers RPC

Package Exports

  • @mdxdb/sqlite
  • @mdxdb/sqlite/durable-object
  • @mdxdb/sqlite/miniflare
  • @mdxdb/sqlite/schema
  • @mdxdb/sqlite/sync

Readme

@mdxdb/sqlite

Cloudflare Durable Objects SQLite adapter for mdxdb.

Each namespace gets its own Durable Object with isolated SQLite storage. Uses Workers RPC for direct method calls on stubs.

Features

  • Namespace isolation: Each namespace (e.g., example.com) gets its own Durable Object with SQLite storage
  • Workers RPC: Call methods directly on Durable Object stubs - no fetch/JSON overhead
  • Full graph support: Things (nodes), Relationships (edges), with bidirectional traversal
  • Vector search ready: Chunked content with embeddings support (client-side embedding)
  • Events & Actions: Immutable event log and durable action tracking
  • Artifacts: Cached compiled content with TTL support
  • Node.js support: Use miniflare for local development and testing

Installation

pnpm add @mdxdb/sqlite

Usage

Cloudflare Workers

import { createMDXClient, MDXDatabase, type Env } from '@mdxdb/sqlite'

// Export the Durable Object class for wrangler.toml
export { MDXDatabase }

export default {
  async fetch(request: Request, env: Env) {
    // Create client for a namespace
    const client = createMDXClient({
      namespace: 'example.com',
      binding: env.MDXDB,
    })

    // CRUD operations
    const post = await client.create({
      ns: 'example.com',
      type: 'Post',
      data: { title: 'Hello World', content: '...' },
    })

    const posts = await client.list({ type: 'Post' })

    // Relationships
    await client.relate({
      type: 'authored',
      from: 'https://example.com/User/alice',
      to: post.url,
    })

    return Response.json(posts)
  }
}

wrangler.toml

name = "my-worker"
compatibility_date = "2024-12-01"

[[durable_objects.bindings]]
name = "MDXDB"
class_name = "MDXDatabase"

[[migrations]]
tag = "v1"
new_sqlite_classes = ["MDXDatabase"]

Node.js with Miniflare

import { createMiniflareClient } from '@mdxdb/sqlite'

// Create client with miniflare backend
const client = await createMiniflareClient({
  namespace: 'example.com',
  persistPath: './.data', // Optional: persist to disk
})

await client.create({
  ns: 'example.com',
  type: 'Post',
  data: { title: 'Hello' },
})

In-Memory Testing

import { createInMemoryBinding, MDXClient } from '@mdxdb/sqlite'

const binding = createInMemoryBinding()
const id = binding.idFromName('test.local')
const stub = binding.get(id)
const client = new MDXClient(stub, 'test.local')

// Use in tests
const thing = await client.create({
  ns: 'test.local',
  type: 'Post',
  data: { title: 'Test' },
})

API

Thing Operations

// Create
const thing = await client.create({
  ns: 'example.com',
  type: 'Post',
  data: { title: 'Hello' },
})

// Read
const thing = await client.get('https://example.com/Post/123')
const thing = await client.getById('Post', '123')

// List
const posts = await client.list({ type: 'Post', limit: 10 })

// Update
await client.update(url, { data: { title: 'Updated' } })

// Upsert
await client.upsert({ ns, type, id, data })

// Delete
await client.delete(url)

// Search
const results = await client.search({ query: 'hello', type: 'Post' })

Relationship Operations

// Create relationship
await client.relate({
  type: 'follows',
  from: userUrl,
  to: otherUserUrl,
})

// Remove relationship
await client.unrelate(from, 'follows', to)

// Get related things
const following = await client.related(userUrl, 'follows', 'from')
const followers = await client.related(userUrl, 'follows', 'to')

// Get relationship objects
const rels = await client.relationships(url, 'follows')

Event Operations

// Track event
const event = await client.track({
  type: 'user.signup',
  source: 'auth',
  data: { userId: '123' },
  correlationId: 'req-456',
})

// Query events
const events = await client.queryEvents({
  type: 'user.signup',
  source: 'auth',
  after: new Date('2024-01-01'),
  limit: 100,
})

Action Operations

// Send action (pending)
const action = await client.send({
  actor: 'user:123',
  object: 'post:456',
  action: 'publish',
})

// Do action (immediately active)
const action = await client.do({
  actor: 'user:123',
  object: 'post:456',
  action: 'publish',
})

// Update action status
await client.startAction(id)
await client.completeAction(id, result)
await client.failAction(id, 'error message')
await client.cancelAction(id)

// Query actions
const pending = await client.queryActions({ status: 'pending' })

Artifact Operations

// Store artifact
const artifact = await client.storeArtifact({
  key: 'post:123:ast',
  type: 'ast',
  source: 'post:123',
  sourceHash: 'abc123',
  content: { type: 'root', children: [] },
  ttl: 3600000, // 1 hour
})

// Get artifact
const artifact = await client.getArtifact('post:123:ast')

// Delete
await client.deleteArtifact(key)

// Clean expired
const count = await client.cleanExpiredArtifacts()

Vector search requires a client-side embedding function:

const client = createMDXClient({
  namespace: 'example.com',
  binding: env.MDXDB,
  embedFn: async (text) => {
    // Call your embedding API (OpenAI, Cloudflare AI, etc.)
    return await embed(text)
  },
})

// Search will automatically embed the query
const results = await client.search({ query: 'machine learning' })

Architecture

┌─────────────────────────────────────────────────────────────┐
│                     Cloudflare Workers                       │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌─────────────┐    RPC    ┌─────────────────────────────┐  │
│  │  MDXClient  │ ───────▶ │  MDXDatabase (Durable Object) │  │
│  └─────────────┘           │  ┌─────────────────────────┐ │  │
│                            │  │   SQLite Storage        │ │  │
│                            │  │  ┌────────────────────┐ │ │  │
│                            │  │  │ things             │ │ │  │
│                            │  │  │ relationships      │ │ │  │
│                            │  │  │ search (chunks)    │ │ │  │
│                            │  │  │ events             │ │ │  │
│                            │  │  │ actions            │ │ │  │
│                            │  │  │ artifacts          │ │ │  │
│                            │  │  └────────────────────┘ │ │  │
│                            │  └─────────────────────────┘ │  │
│                            └─────────────────────────────┘  │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Each namespace (example.com, app.dev, etc.) maps to a unique Durable Object instance with its own SQLite database.

License

MIT