</> jsorm
Switch landing language
Modern ORM for typed SQL workflows

JSORM — JSON-first ORM for TypeScript

Build type-safe queries using a JSON-like API, powered by AST-based SQL generation.

JSON API

Structured reads, writes, and relation mutations.

AST

Predictable SQL generation with explicit shape.

TypeScript

Inference from model definitions, not duplicated interfaces.

query.ts
const users = await db.get(User, {
  select: {
    name: true,
    role: { name: true },
  },
  where: {
    active: true,
  },
});

What is jsorm

A JSON-first ORM with explicit SQL behavior

jsorm combines typed model definitions, a structured query AST, and adapter-based execution so teams can keep strong TypeScript ergonomics without hiding how SQL is built.

How jsorm compares

Query style

jsorm

JSON-like objects backed by a structured AST

traditional

Chains, decorators, or handwritten query builders

Typing

jsorm

Inference from defineModel() as single source of truth

traditional

Manual interfaces or duplicated types are common

SQL visibility

jsorm

AST and executeSql() keep SQL behavior explicit

traditional

Magic layers can hide generated SQL details

jsorm is built for teams that want readable JSON-like queries, strong TypeScript inference, and the ability to reason about SQL instead of trusting hidden runtime magic.

It separates model definition, field metadata, query building, adapter execution, and migration runtime so each concern stays clear and extensible.

The result is a workflow that feels higher level than raw SQL, but still honest about the SQL being generated.

Core features

Designed for modern TypeScript backends

Every feature is built around a single source of truth: your model definition and the structured AST derived from it.

JSON-first queries

Describe reads and writes with plain objects instead of opaque chain builders.

await db.get(User, {
  select: { id: true, role: { name: true } },
  where: { active: true },
});

Typed models and inference

Define schemas once and infer records plus input types directly from models.

const User = defineModel('users', {
  id: t.number().primary(),
  name: t.string(),
  role: t.belongsTo(Role),
});

Explicit relations

Use belongsTo, hasOne, hasMany, and manyToMany with predictable SQL behavior.

const Post = defineModel('posts', {
  author: t.belongsTo(User),
  tags: t.manyToMany(Tag),
});

Multi-database support

Orchestrate PostgreSQL, MySQL, and SQLite connections from one typed entry point.

const db = connectionDB({
  databases: {
    main: pgAdapter({ connectionString }),
    cache: sqliteAdapter({ file: ':memory:' }),
  },
});

Raw SQL when needed

Keep full SQL power available through executeSql() without abandoning the JSON API.

await db.executeSql(
  'SELECT COUNT(*) AS count FROM users WHERE active = ?',
  [true],
);

Optional migrations

Connect to an existing database immediately or opt into migration runtime and CLI.

const source = defineConnectionSource({
  adapter: pgAdapter({ connectionString }),
});

Code examples

Readable abstractions, predictable output

Use jsorm for schemas, nested reads, relation mutations, and multi-database orchestration without losing control of what reaches the database.

Model definition

example.ts
const Role = defineModel('roles', {
  id: t.number().primary(),
  name: t.string().unique(),
});

const User = defineModel('users', {
  id: t.number().primary(),
  name: t.string(),
  role: t.belongsTo(Role),
});

Insert with relations

example.ts
await db.insert(User, {
  name: 'Alice',
  role: { connect: 1 },
  profile: {
    create: { bio: 'Builder' },
  },
});

Select nested data

example.ts
const rows = await db.get(User, {
  select: {
    id: true,
    name: true,
    role: { name: true },
  },
  where: {
    role: {
      name: { eq: 'admin' },
    },
  },
});

Why jsorm

Built for engineers who want clarity, not hidden magic

The architecture favors explicit modeling, adapter boundaries, and extensibility over clever shortcuts.

Expressive API with explicit structure
No hidden magic between JSON, AST, and SQL
Full SQL power stays available when abstraction is not enough
Modular packages for adapters and future ecosystem growth

Ecosystem

Modular packages for a flexible ORM stack

Install only what you need. Keep the core package lightweight while adapters wrap official drivers.

pnpm add jsorm jsorm-pg jsorm-sqlite jsorm-mysql

jsorm

Core ORM, model system, query AST, migrations, CLI, and adapter contracts.

jsorm-pg

PostgreSQL adapter built around official pg driver patterns.

jsorm-sqlite

SQLite adapter for lightweight apps, local tools, and tests.

jsorm-mysql

MySQL adapter for production services and analytics workloads.