scriba-sdk
v1.0.2
Published
Scriba is a minimalist, reactive, SQLite-powered ORM designed with one radical principle:
Readme
📝 Scriba — The Zero-Learning Curve Reactive ORM
Scriba is a minimalist, reactive, SQLite-powered ORM designed with one radical principle:
“If it feels like working with plain JavaScript objects, you're doing it right.”
Forget complex schemas, migrations, data mappers, or cryptic APIs. Scriba turns every database row into a live object: accessing a property loads it lazily, updating it writes to the database instantly, and relations behave like native properties.
Scriba is not just an ORM — it is the easiest and most intuitive persistence layer you can use in JavaScript.
🚀 Features
Zero Learning Curve You work with normal JS objects. No
.save(),.update(),.populate(),.from(), or.select().Auto-Persisting Objects Assigning a property automatically updates SQLite:
user.name = "Alice"; // Writes instantly to DBLazy Loading Accessing a field loads it on demand:
user = User[3]; // Auto SELECT * WHERE id = 3Reactive Records Subscribe to live updates:
user.subscribe(u => console.log("Updated:", u));1:N and N:N Relations Automatically Resolved If your schema defines relations, you get:
user.posts; // Auto SELECT posts user.roles; // Auto SELECT through join tableType-Aware Fields JSON → JS object datetime → Date instance boolean → native boolean
Hot Schema Reload (with auto-migrations) Update your
.scribaschema file and watch your tables update automatically.Multi-Tenant by Design Each tenant gets its own isolated SQLite database and schema.
📦 Installation
npm install scriba(or whatever your real package name will be)
🧠 How It Works
Scriba uses four core abstractions:
Scriba
Multi-tenant manager, schema loader, table initializer.
TenantProxy
Gives easy access to entities inside a tenant.
TableProxy
Represents a database table. Responsible for:
- lazy loading
- record caching
- inserts
- queries
- relation metadata
RecordProxy
Represents a single record.
Through a JavaScript Proxy, it intercepts:
get→ loads relations, parses types, returns cached valuesset→ normalizes, auto-updates SQLite, notifies subscribers, invalidates caches
🧩 Basic Usage
1. Initialize Scriba
import Scriba from "scriba";
const scriba = new Scriba([
{ id: "app", path: "./app.db", schema: "./schema.scriba" }
]);2. Define a Schema (schema.scriba)
model User {
id int
name text
age int
}
model Post {
id int
userId int
title text
content text
}Scriba automatically:
- creates tables if they don’t exist
- adds missing columns
- reloads when the file changes
3. Insert Data
const tenant = scriba.tenant("app");
const User = tenant.entity("User");
const alice = await User.push({
name: "Alice",
age: 25
});4. Fetch Data (lazy)
const u = User[1]; // Auto SELECT
console.log(u.name);5. Auto-Saving
u.age = 26;
// Immediately: UPDATE User SET age = 26 WHERE id = 16. Relations (zero configuration)
If the schema contains something like userId, Scriba exposes:
u.posts;
// SELECT * FROM Post WHERE userId = u.id7. Reactive Subscriptions
u.subscribe(user => {
console.log("User updated:", user);
});Now any assignment triggers the subscriber.
🔥 Example: Many-to-Many
Assume the schema:
model User {
id int
name text
}
model Role {
id int
label text
}
model UserRole {
userId int
roleId int
}Scriba detects User ↔ Role via UserRole.
Then you get:
user.roles; // Auto SELECT through join table📊 Querying
Simple, expressive:
User.query(
{ age: { $gt: 18 } },
{ sort: "age DESC", limit: 10 }
);Returns real RecordProxy instances.
❤️ Why Scriba?
While traditional ORMs (Prisma, Sequelize, Drizzle) require learning large APIs or DSLs, Scriba has one goal:
Make database persistence feel like normal JavaScript.
- No
.save() - No
.update() - No
.populate() - No decorators, models, or classes
- No migrations to write manually
Just:
const tenant = scribe.tentant("database");
const user = tenant.entity("User");
user[1].name = "New Name";
console.log(user.posts);
If you know JavaScript, you already know Scriba.
📄 License
MIT Use freely, modify freely.
