Getting started
This guide walks through a complete flow: configure jsorm.config.ts, define models, create a runtime instance, and run typed queries.
-
Define models
Import
defineModelandt. One definition drives both TypeScript inference and runtime metadata.// src/schema/main/user.tsimport { defineModel, t } from '@jsorm/core';export const Role = defineModel('roles', {id: t.number().primary(),name: t.string().unique(),});export const User = defineModel('users', {id: t.number().primary(),name: t.string(),email: t.string().optional(),active: t.boolean().default(true),createdAt: t.date(),role: t.belongsTo(Role),});Export inferred types when needed:
import type { InferInput, InferModel } from '@jsorm/core';type UserRecord = InferModel<typeof User>;type UserInput = InferInput<typeof User>; -
Create
jsorm.config.tsKeep one config for runtime + CLI:
// jsorm.config.tsimport { defineConnectionSource, defineJsormConfig } from '@jsorm/core';import { pgAdapter } from '@jsorm/pg';const main = defineConnectionSource({adapter: pgAdapter({name: 'main',connectionString: process.env.DATABASE_URL!,pool: { min: 2, max: 10 },}),});export default defineJsormConfig({connectionSources: { main },defaults: {connectionSource: 'main',},}); -
Create a runtime instance
Use
createJsorm()for Node runtime boundaries:import { createJsorm } from '@jsorm/core';const db = await createJsorm().init();If you ran
pnpm exec jsorm init, you can also start from the generateddb.tshelper. -
Insert data
await db.insert(User, {name: 'Alice',email: 'alice@example.com',createdAt: new Date(),role: { connect: 1 },}); -
Read typed data
const users = await db.get(User, {select: {id: true,name: true,role: { name: true },},where: {active: true,role: { name: { eq: 'admin' } },},orderBy: [{ name: 'asc' }],});// users: Array<{ id: number; name: string; role: { name: string } }> -
Update and delete safely
whereis required on write operations.await db.update(User, {data: { active: false },where: { id: { eq: 10 } },});await db.delete(User, {where: { id: { eq: 10 } },});
Raw SQL
Section titled “Raw SQL”Use the namespaced escape hatch only: db.raw.*.
const rows = await db.raw.execute( 'SELECT COUNT(*) AS total FROM users WHERE active = $1', [true],);
const compiled = await db.raw.compile( 'SELECT id, name FROM users WHERE active = $1', [true],);Health check and shutdown
Section titled “Health check and shutdown”const health = await db.healthCheck();// { main: 'ok' }
process.on('SIGTERM', async () => { await db.close(); process.exit(0);});Testing runtime
Section titled “Testing runtime”For isolated tests, use createJsormTest():
import { createJsormTest } from '@jsorm/core';
const testDb = await createJsormTest().init();Best practices
Section titled “Best practices”- Use
createJsorm()from@jsorm/corein Node runtime code, or from@jsorm/runtimein edge/fetch-only code. - Use
createJsormTest()for test isolation instead of sharing app runtime state. - Keep
whereclauses explicit on all writes. - Prefer JSON DSL as default; reserve
db.raw.*for cases the DSL cannot express cleanly. - Keep CLI, migrations, and deploy steps on
@jsorm/node.