Skip to main content

Storage Adapters

jcell uses a pluggable adapter pattern — the same API works across different storage backends.

import { createDB } from '@sajjadbzn/jcell'

// Pick your adapter:
const db = createDB({ adapter: memoryAdapter() })
// or fileAdapter({ path: './data' })
// or sqliteAdapter({ path: './app.db' })
// or d1Adapter({ binding: env.DB })

Strategy Pattern

Adapters support two operational strategies:

  • Cache — Loads all documents into memory, filters/sorts in JS. Used by file and memory adapters.
  • Delegate — Delegates queries to the backend (SQL). Used by SQLite and D1 adapters for efficient SQL-level filtering.

File Adapter

Persists each collection as a JSON file on disk. Best for small to medium projects that need persistence without a database server.

import { fileAdapter } from '@sajjadbzn/jcell'

const db = createDB({
adapter: fileAdapter({ path: './data' })
})

Features

  • Atomic writes — writes to a temp file, then renames over the target
  • Crash recovery.bak backup files if the main file gets corrupted
  • Write queue — serialized writes per collection (no race conditions)
  • Delegate strategy — in-memory filtering for efficient queries

File Structure

./data/
users.json # Collection: users
posts.json # Collection: posts
users.json.bak # Auto-backup after write
posts.json.bak

Configuration

OptionDefaultDescription
path'./data'Directory for collection JSON files

Memory Adapter

Stores everything in a Map. Data is lost when the process exits.

import { memoryAdapter } from '@sajjadbzn/jcell'

const db = createDB({ adapter: memoryAdapter() })

Best Uses

  • Unit tests — fast, isolated, no cleanup needed
  • Serverless functions — data lives only for the request lifetime
  • Prototyping — rapid iteration without file I/O

Configuration

No options needed.

SQLite Adapter

Uses better-sqlite3 to store data in a local SQLite database with full SQL query support.

npm install better-sqlite3
import { sqliteAdapter } from '@sajjadbzn/jcell'

const db = createDB({
adapter: sqliteAdapter({ path: './app.db' })
})

Features

  • Real SQL DDL — schemas auto-generate CREATE TABLE statements
  • Parameterized queries — safe from SQL injection
  • Native indexes — real SQL-level indexes
  • WAL mode — better concurrent read performance
  • Foreign key enforcement — for reference fields
  • Transactions — atomic multi-operation transactions

Configuration

OptionDefaultDescription
path'./data.db'Path to the SQLite database file
tablePrefix''Optional table name prefix (e.g. "jcell_")

D1 Adapter

Connects to Cloudflare D1, Cloudflare's serverless SQLite database available in Workers.

import { d1Adapter } from '@sajjadbzn/jcell/d1'

// In your Worker:
export default {
async fetch(request, env) {
const db = createDB({
adapter: d1Adapter({ binding: env.DB })
})
// ...
}
}

Features

  • SQL DDL — auto-creates tables from schemas
  • Parameterized queries — uses D1's bound parameters
  • Batch operations — for efficient multi-document writes
  • Transactions — via D1's batch API
  • Indexes — real SQL indexes

Import Path

Import from @sajjadbzn/jcell/d1 — this subpath avoids Node.js APIs so it works in the Workers runtime.

Configuration

OptionDefaultDescription
binding(required)A Cloudflare D1 database binding
tablePrefix''Optional table name prefix

Adapter Comparison

FeatureFileMemorySQLiteD1
Persistence✅ Disk❌ Ephemeral✅ Disk✅ Cloud
StrategyCache/DelegateCache/DelegateDelegateDelegate
Transactions
Native Indexes
Aggregation✅ JS✅ JS✅ SQL✅ SQL
RuntimeNode/BunAnyNode/BunWorkers
External DepsNoneNonebetter-sqlite3None