Introduction
UnrealORM
Section titled “UnrealORM”A modern, type-safe ORM for SurrealDB. Native SurrealDB power, full TypeScript safety, zero abstraction—no decorators, no magic, just classes and functions.
UnrealORM builds on top of the official surrealdb package, providing a TypeScript ORM experience while preserving full access to SurrealDB’s native features. Define your schema once in code, and the ORM handles type inference, DDL generation, and schema synchronization.
Note: UnrealORM 1.0.0-alpha.x requires SurrealDB’s 2.0 (alpha) JS SDK. If you’re using 1.x of their SDK, install unreal-orm@0.6.0 instead. To upgrade, see the Migration Guide.
Quick Start
Section titled “Quick Start”bunx @unreal-orm/cli init
# Or with other package managersnpx @unreal-orm/cli initpnpm dlx @unreal-orm/cli inityarn dlx @unreal-orm/cli initThis will:
- Set up your project structure (
unreal/folder) - Configure database connection (
surreal.ts) - Install dependencies (
unreal-orm,surrealdb,@unreal-orm/cli) - Optionally generate sample tables or import from existing database
Manual installation
# Using bunbun add unreal-orm@latest surrealdb@latestbun add -D @unreal-orm/cli@latest
# Using pnpmpnpm add unreal-orm@latest surrealdb@latestpnpm add -D @unreal-orm/cli@latest
# Using npmnpm install unreal-orm@latest surrealdb@latestnpm install -D @unreal-orm/cli@latest
# Using yarnyarn add unreal-orm@latest surrealdb@latestyarn add -D @unreal-orm/cli@latestFeatures
Section titled “Features”- Type-safe models — Define tables as classes with full TypeScript inference for fields, queries, and results
- Schema sync — Generate DDL from code with
applySchema(), or generate code from database withunreal pull - Relations — Typed record links with automatic hydration via
fetch - Native SurrealQL & query builder — Use
surqltemplates and functional expressions directly, or filter with typed field proxies inselect,count,updateMany, anddeleteMany - Indexes — Define unique, composite, and search indexes with full type safety
- Custom methods — Add instance and static methods to your models
- CLI tools —
init,pull,push,diff,mermaidfor schema management
Example
Section titled “Example”import { Surreal, surql } from "surrealdb";import { Table, Field, Index, Unreal } from "unreal-orm";
// Define a User model with validation and custom methodsclass User extends Table.normal({ name: "user", fields: { name: Field.string(), email: Field.string({ assert: surql`$value CONTAINS "@"` }), createdAt: Field.datetime({ default: surql`time::now()` }), },}) { getDisplayName() { return `${this.name} <${this.email}>`; }}
// Define a unique indexconst idx_user_email = Index.define(() => User, { name: "idx_user_email", fields: ["email"], unique: true,});
// Define a Post with a relation to Userclass Post extends Table.normal({ name: "post", fields: { title: Field.string(), content: Field.string(), author: Field.record(() => User), },}) {}
async function main() { const db = new Surreal(); await db.connect("ws://localhost:8000", { namespace: "test", database: "test", authentication: { username: "root", password: "root" }, });
// Apply schema to database await Unreal.applySchema(db, [User, idx_user_email, Post]);
// Create records const user = await User.create(db, { name: "Alice", email: "alice@example.com", }); const post = await Post.create(db, { title: "Hello", content: "World", author: user.id, });
// Query with hydrated relations const result = await Post.select(db, { from: post.id, only: true, fetch: ["author"], }); console.log(result.author.getDisplayName()); // "Alice <alice@example.com>"
// Update with explicit mode await user.update(db, { data: { name: "Alice Smith" }, mode: "merge" });
await db.close();}See the Hands-on Tutorial for a complete walkthrough building a blog API with users, posts, comments, and relations.
Type-Safe Select
Section titled “Type-Safe Select”Select specific fields with full type inference:
import { typed } from "unreal-orm";import { surql } from "surrealdb";
// Nested object fields - types inferred from objectSchemaconst posts = await Post.select(db, { select: { title: true, metadata: { category: true } },});// Type: { title: string; metadata: { category: string } }[]
// Nested record fields - types inferred from linked tableconst posts = await Post.select(db, { select: { title: true, author: { name: true, email: true } },});// Type: { title: string; author: { name: string; email: string } }[]
// Computed fields with typed() helperconst posts = await Post.select(db, { select: { title: true, commentCount: typed<number>(surql`count(<-comment)`) },});// Type: { title: string; commentCount: number }[]
// Type-safe omit - exclude fields from resultconst users = await User.select(db, { omit: { password: true, secret: true },});// Type: Omit<User, 'password' | 'secret'>[]Type-Safe Query Builder
Section titled “Type-Safe Query Builder”Use the callback-based where API for fully typed filters with IntelliSense:
import { and, or, eq, gt } from "unreal-orm";
// SELECT with typed filtersconst posts = await Post.select(db, { where: (f) => f.views.gt(100),});
// Use SurrealDB string/array/date functions on columnsconst recent = await Post.select(db, { where: (f) => f.title.toLowerCase().contains("surreal"),});
// Native function namespaces cover the entire SurrealDB function surfaceconst filtered = await Post.select(db, { where: (f) => and( f.title.string.starts_with("hello"), f.views.math.round().eq(100), ),});
// Compose logical expressionsconst featuredTech = await Post.select(db, { where: (f) => and( eq(f.metadata.category, "tech"), or(f.metadata.featured.eq(true), gt(f.views, 1000)), ),});
// COUNT, UPDATE, and DELETE also accept callbacksconst popular = await Post.count(db, { where: (f) => f.views.gt(100),});
await Post.updateMany(db, { where: (f) => f.metadata.category.eq("tech"), data: { views: 0 }, mode: "merge",});
await Post.deleteMany(db, { where: (f) => f.tags.contains("deprecated"),});Available operators include eq, ne, gt, gte, lt, lte, exact (==), isNone, isNull, isTrue, isFalse, inside, outside, intersects, matches (full-text @@), isIn, isNotIn, containsAny, containsAll, containsNone, plus logical helpers and, or, not (all available as both column methods and standalone helpers).
Arithmetic operators (add, subtract, multiply, divide, modulo) return ColumnRef for chaining:
// WHERE views + 10 > 100const trending = await Post.select(db, { where: (f) => f.views.add(10).gt(100),});Graph traversal (out, in, both) for ->, <-, <-> operators:
// WHERE author->follow->user.name = "Alice"const posts = await Post.select(db, { where: (f) => f.author.out("follow").out("user").name.eq("Alice"),});Columns expose all native SurrealDB function namespaces: string, math, array, time, is, meta, parse, bytes, crypto, duration, encoding, geo, http, object, rand, record, search, session, type, vector. Any built-in function can be called, e.g. f.title.string.lowercase(), f.views.math.round(2), f.password.crypto.sha256(), f.location.geo.distance(other). Nested functions with :: use bracket notation: f.title.string['similarity::jaro']().
Runtime availability depends on the connected SurrealDB version; full-text matches() requires a SEARCH index, search::* and vector::* require SurrealDB 2.x+, and regex operators such as ~ and !~ were removed in SurrealDB 3.x.
The CLI helps manage schema synchronization between your code and database:
unreal init # Initialize project with connection and sample tablesunreal pull # Generate TypeScript models from database schemaunreal push # Apply TypeScript schema to databaseunreal diff # Compare code vs database schemaunreal mermaid # Generate ERD diagramunreal view # Interactive TUI for browsing/editing recordsunreal docs # Open the UnrealORM documentationunreal github # Open the UnrealORM GitHub repositoryAfter init, the CLI is installed as a dev dependency and can be run via bunx unreal or npx unreal.
Documentation
Section titled “Documentation”- Getting Started — Installation and setup
- Hands-on Tutorial — Build a blog API step-by-step
- Capabilities — Supported SurrealDB features
- API Reference — Full API documentation
- Migration Guide — Upgrading from 0.x
Community
Section titled “Community”- 💬 GitHub Discussions — Questions & ideas
- 🐛 Issues — Bug reports
- 🤝 Contributing — How to contribute
- ⭐ Star on GitHub — Show support
- ☕ Ko-fi — Buy me a coffee
Author
Section titled “Author”UnrealORM is created and maintained by Jimpex.