jotdb
v0.1.8
Published
[](https://deploy.workers.cloudflare.com/?url=https://github.com/acoyfellow/jotdb)
Readme
JotDB
A lightweight, schema-less database built on Cloudflare Durable Objects. Think of it as Firestore's security rules, but with Zod validation built-in. Perfect for both internal and external APIs, with automatic type safety and validation.
Cloudflare Products: JotDB works with any Cloudflare product that supports Durable Objects:
- Cloudflare Workers
- Cloudflare Pages (with Functions)
- Cloudflare Workflows
- Cloudflare Queues
- Cloudflare Cron Triggers
Why JotDB?
JotDB combines the best of both worlds: the simplicity of NoSQL with the safety of schema validation. Here's what makes it special:
- Built-in Type Safety: Automatic Zod validation ensures your data is always in the right shape
- Edge-Native: Runs directly on Cloudflare's edge network, with sub-millisecond latency
- RPC-First: Direct method calls instead of HTTP endpoints (though you can easily wrap it in HTTP)
- Durable Storage: Built on Durable Objects for reliable, consistent storage
- Zero Setup: No database configuration, no connection strings, just instantiate and go
- Perfect for APIs: Use it as an internal database or wrap it with auth for external APIs
- Real-time Ready: Durable Objects provide strong consistency guarantees
Perfect for:
- Quick prototypes that need data validation
- Small to medium applications that need reliable storage
- Serverless environments where you want type safety
- Real-time data storage with strong consistency
- Collaborative applications that need data validation
- APIs that need both flexibility and safety
Design Patterns
JotDB uses Cloudflare Durable Objects under the hood, which means you can organize your data in several ways:
Global Store: Use a single instance for your entire application
const db = env.JOTDB.get(env.JOTDB.idFromName("global"));Per-User Store: Create a separate instance for each user
const userDb = env.JOTDB.get(env.JOTDB.idFromName(`user:${userId}`));Per-Event Store: Create temporary stores for events or sessions
const eventDb = env.JOTDB.get(env.JOTDB.idFromName(`event:${eventId}`));
Each instance is isolated and can have its own schema and options. This follows the Actor Model pattern, where each instance is an independent actor that manages its own state.
Installation
# Using npm
npm install jotdb
# Using yarn
yarn add jotdb
# Using pnpm
pnpm add jotdbConfigure wrangler.jsonc
{
"durable_objects": {
"bindings": [
{
"name": "JOTDB",
"class_name": "JotDB"
}
]
}
}Full Example
import { JotDB } from 'jotdb';
export interface Env {
JOTDB: DurableObjectNamespace;
}
export default {
async fetch(request: Request, env: Env) {
// Initialize the database
const jotId = env.JOTDB.idFromName("my-db");
const db = env.JOTDB.get(jotId);
// Example operations
await db.set("user:123", { name: "John", age: 30 });
const user = await db.get("user:123");
await db.delete("user:123");
// Return the result
return new Response(JSON.stringify({ user }), {
headers: { 'Content-Type': 'application/json' }
});
}
};API Reference
| Method | Description | Parameters | Returns |
|--------|-------------|------------|---------|
| set(key, value) | Store a value | key: string, value: any | Promise<void> |
| get(key) | Retrieve a value | key: string | Promise<any> |
| delete(key) | Remove a value | key: string | Promise<void> |
| clear() | Remove all values | none | Promise<void> |
| keys() | Get all keys | none | Promise<string[]> |
| has(key) | Check if key exists | key: string | Promise<boolean> |
| getAll() | Get all data | none | Promise<Record<string, unknown> \| unknown[]> |
| setAll(objOrArr) | Set all data at once | objOrArr: Record<string, unknown> \| unknown[] | Promise<void> |
| push(item) | Add item to array | item: unknown | Promise<void> |
| getSchema() | Get current schema | none | Promise<SchemaDefinition> |
| setSchema(schema) | Set data schema | schema: SchemaDefinition | Promise<void> |
| getOptions() | Get current options | none | Promise<JotDBOptions> |
| setOptions(opts) | Set database options | opts: Partial<JotDBOptions> | Promise<void> |
| getAuditLog() | Get audit log entries | none | Promise<AuditLogEntry[]> |
| clearAuditLog() | Clear audit log | none | Promise<void> |
Options
interface JotDBOptions {
autoStrip: boolean; // Automatically strip unknown fields
readOnly: boolean; // Enable read-only mode
}Schema Types
type SchemaType = "string" | "number" | "boolean" | "email" | "array" | "object" | "any";License
MIT License - feel free to use this in your own projects!
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Testing
Currently, testing is done manually in production. We're working on adding a comprehensive test suite. For now, you can test the functionality by:
- Deploying to Cloudflare Workers
- Using the example endpoints
- Verifying data persistence
