Schema
Define database tables using TypeScript and sync them automatically.
Quick Start
typescript
import { Database, model, string, number, boolean } from "kyrin";
// Define a model
const User = model("users", {
// id: number(),
// currently kyrin handle auto define id attribute name 'id'
// on create table but we have plan to define primary key function for optional use
name: string(),
email: string().optional(),
isActive: boolean().default(true),
});
// Create database and sync
const db = new Database({ type: "sqlite", filename: "./app.db" });
db.register(User);
db.sync({ force: true }); // Creates tableType Functions
| Function | SQL Type | Example |
|---|---|---|
string() | TEXT | name: string() |
number() | INTEGER | age: number() |
boolean() | INTEGER (0/1) | active: boolean() |
date() | TEXT (ISO) | createdAt: date() |
Modifiers
Chain modifiers to customize column behavior:
typescript
const Post = model("posts", {
// id: number(),
// currently kyrin handle auto define id attribute name 'id'
// on create table but we have plan to define primary key function for optional use
title: string(),
subtitle: string().optional(), // NULL allowed
views: number().default(0), // Default value
tags: string().array(), // Stored as JSON
deletedAt: date().nullable(), // Explicit NULL
});| Modifier | Effect |
|---|---|
.optional() | Removes NOT NULL |
.default(value) | Adds DEFAULT clause |
.nullable() | Allows NULL |
.array() | Stored as JSON TEXT |
Syncing
Force Mode (Development)
Drops and recreates tables. ⚠️ Data loss!
typescript
db.sync({ force: true });Safe Mode (Production)
Creates tables if not exist, adds new columns only.
typescript
db.sync(); // Safe by defaultDry Run
Returns SQL without executing:
typescript
const sql = db.sync({ dryRun: true });
console.log(sql);
// ["CREATE TABLE IF NOT EXISTS users ...", ...]CRUD Operations
All operations are performed through the model:
Create
typescript
const user = User.create(db, {
name: "John",
email: "john@example.com",
});
console.log(user.id); // Auto-generated IDFind All
typescript
// All records
const users = User.findAll(db);
// With filter
const activeUsers = User.findAll(db, { isActive: true });Find One
typescript
const user = User.findOne(db, { id: 1 });
if (user) {
console.log(user.name);
}Update
typescript
User.update(db, { id: 1 }, { name: "Jane" });Delete
typescript
User.delete(db, { id: 1 });Type Inference
Access the inferred TypeScript type:
typescript
const User = model("users", {
// id: number(),
// id: number(), currently kyrin handle auto define id attribute name 'id'
// on create table but we have plan to define primary key function for optional use
name: string(),
email: string().optional(),
});
// Get type from model
type UserType = typeof User.$type;
// UserType = {
// id: number;
// name: string;
// email?: string;
// }Generated SQL
The id column is automatically set as PRIMARY KEY AUTOINCREMENT:
typescript
const User = model("users", {
// id: number(),
// currently kyrin handle auto define id attribute name 'id'
// on create table but we have plan to define primary key function for optional use
name: string(),
isActive: boolean().default(true),
});
User.toCreateSQL();
// CREATE TABLE IF NOT EXISTS users (
// id INTEGER PRIMARY KEY AUTOINCREMENT,
// name TEXT NOT NULL,
// isActive INTEGER NOT NULL DEFAULT 1
// )Multiple Models
Register multiple models at once:
typescript
const User = model("users", { ... });
const Post = model("posts", { ... });
const Comment = model("comments", { ... });
db.register(User, Post, Comment);
db.sync({ force: true });Best Practices
- Use
force: trueonly in development - It drops all data - Always have an
idcolumn - Auto-generates primary key - Use
.optional()for nullable fields - Cleaner than.nullable() - Use
.default()for sensible defaults - Reduces null checks