UNPKG

@aradox/multi-orm

Version:

Type-safe ORM with multi-datasource support, row-level security, and Prisma-like API for PostgreSQL, SQL Server, and HTTP APIs

370 lines (293 loc) 7.54 kB
# Quick Reference Card **One-page reference for common ORM operations** --- ## Setup ```typescript import { ORMClient } from '@your-org/orm'; import * as fs from 'fs'; const schema = fs.readFileSync('./orm.qts', 'utf-8'); const orm = new ORMClient(schema, { schemaPath: './orm.qts' }); const db = orm.generate(); ``` --- ## Query Operations ### Find Many ```typescript const users = await db.User.findMany({ where: { role: { eq: 'admin' } }, orderBy: { created_at: 'desc' }, skip: 0, take: 10 }); ``` ### Find Unique ```typescript const user = await db.User.findUnique({ where: { id: 123 } }); ``` ### Find First ```typescript const firstAdmin = await db.User.findFirst({ where: { role: { eq: 'admin' } } }); ``` ### Count ```typescript const count = await db.User.count({ where: { is_active: { eq: true } } }); ``` --- ## CRUD Operations ### Create ```typescript const user = await db.User.create({ data: { email: 'john@example.com', name: 'John Doe', role: 'user', tenant_id: 1 } }); ``` ### Create Many ```typescript const result = await db.User.createMany({ data: [ { email: 'user1@example.com', name: 'User 1', role: 'user', tenant_id: 1 }, { email: 'user2@example.com', name: 'User 2', role: 'user', tenant_id: 1 } ] }); console.log(`Created ${result.count} users`); ``` ### Update ```typescript const updated = await db.User.update({ where: { id: 123 }, data: { name: 'Jane Updated' } }); ``` ### Update Many ```typescript const result = await db.User.updateMany({ where: { role: { eq: 'user' } }, data: { is_active: true } }); ``` ### Delete ```typescript const deleted = await db.User.delete({ where: { id: 123 } }); ``` ### Delete Many ```typescript const result = await db.User.deleteMany({ where: { is_active: { eq: false } } }); ``` ### Upsert ```typescript const user = await db.User.upsert({ where: { email: 'john@example.com' }, create: { email: 'john@example.com', name: 'John Doe', role: 'user', tenant_id: 1 }, update: { name: 'John Updated' } }); ``` --- ## Where Operators ### Comparison ```typescript { price: { eq: 99.99 } } // Equal { price: { ne: 0 } } // Not equal { price: { gt: 50 } } // Greater than { price: { gte: 50 } } // Greater than or equal { price: { lt: 100 } } // Less than { price: { lte: 100 } } // Less than or equal { status: { in: ['active', 'pending'] } } { status: { notIn: ['deleted', 'archived'] } } ``` ### String ```typescript { email: { contains: '@example.com' } } // LIKE '%value%' { name: { startsWith: 'John' } } // LIKE 'value%' { phone: { endsWith: '1234' } } // LIKE '%value' ``` ### Null ```typescript { name: { isNull: true } } // IS NULL { email: { isNotNull: true } } // IS NOT NULL ``` ### Logical ```typescript // AND (implicit) { is_active: { eq: true }, role: { eq: 'admin' } } // OR { OR: [{ role: { eq: 'admin' } }, { role: { eq: 'moderator' } }] } // NOT { NOT: { status: { eq: 'banned' } } } ``` --- ## Relations ```typescript const users = await db.User.findMany({ include: { orders: { where: { status: { eq: 'completed' } }, take: 5 } } }); ``` --- ## Field Selection ```typescript const users = await db.User.findMany({ select: { id: true, email: true, name: true } }); ``` --- ## Middleware ### Register Middleware ```typescript import { tenantIsolationMiddleware, rbacMiddleware, auditLoggingMiddleware } from '@your-org/orm/middleware/examples'; db.use(tenantIsolationMiddleware(['Customer', 'Order'])); db.use(rbacMiddleware({ 'Invoice': ['admin', 'finance'] })); db.use(auditLoggingMiddleware({ async log(entry) { ... } })); ``` ### Set Context ```typescript db.setContext({ user: { id: session.user.id, tenantId: session.user.tenantId, role: session.user.role } }); ``` --- ## Environment Variables ```bash # Database DATABASE_URL="Server=localhost;Database=MyDB;Integrated Security=true;TrustServerCertificate=true" # Logging LOG_LEVEL=debug # off, error, warn, info, debug LOG_MODULES=mssql,postgres # Comma-separated module names ``` --- ## CLI Commands ```bash npm run generate # Generate types from schema npm run validate # Validate schema npm run build # Build TypeScript ``` --- ## Debug SQL Queries ```bash # Windows $env:LOG_LEVEL="debug"; $env:LOG_MODULES="mssql"; node dist/app.js # Linux/Mac LOG_LEVEL=debug LOG_MODULES=mssql node dist/app.js ``` --- ## Schema Example ```typescript config { maxIncludeDepth = 5 maxFanOut = 100 strictMode = false } datasource main_db { provider = "sqlserver" url = env("DATABASE_URL") } model User @datasource(main_db) { id Int @id @default(autoincrement()) email String @unique name String? role String tenant_id Int created_at DateTime? orders Order[] @relation(fields:[id],references:[user_id],strategy:"lookup") } model Order @datasource(main_db) { id Int @id @default(autoincrement()) user_id Int total Float status String? tenant_id Int user User @relation(fields:[user_id],references:[id],strategy:"lookup") } ``` --- ## Connection Strings ### SQL Server - Windows Auth ``` Server=MYSERVER;Database=MyDB;Integrated Security=true;TrustServerCertificate=true ``` ### SQL Server - SQL Auth ``` Server=localhost;Database=MyDB;User Id=sa;Password=yourPassword;Encrypt=true ``` ### PostgreSQL ``` postgresql://user:password@localhost:5432/mydb?schema=public ``` --- ## Best Practices **DO:** - Generate types after schema changes: `npm run generate` - Set context per request (not globally) - Use defense in depth (DB RLS + middleware + API validation) - Always call `db.$disconnect()` when done - Handle middleware errors appropriately **DON'T:** - Expose ORM client to frontend (use API layer) - Trust user input for `tenant_id` (use session value) - Set global context (causes race conditions) - Forget to regenerate types after schema changes --- ## Error Handling ```typescript try { const customers = await db.Customer.findMany({}); return NextResponse.json({ customers }); } catch (error) { if (error.message.includes('RBAC:')) { return NextResponse.json({ error: 'Forbidden' }, { status: 403 }); } if (error.message.includes('Tenant isolation:')) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } console.error('Database error:', error); return NextResponse.json({ error: 'Internal error' }, { status: 500 }); } ``` --- ## Full Documentation 📚 **[Complete User Guide](./USER_GUIDE.md)** - Comprehensive documentation ### Quick Links - [User Guide](./USER_GUIDE.md) - Complete documentation - [Hooks & Middleware Guide](./HOOKS_MIDDLEWARE_GUIDE.md) - RLS and middleware - [SQL Logging Guide](./SQL_LOGGING_GUIDE.md) - Debug queries - [CRUD Guide](./CRUD_GUIDE.md) - CRUD operations - [AI Coding Guide](./AI_CODING_GUIDE.md) - Multi-tenant apps --- **Version:** 1.0.0 **Last Updated:** November 17, 2025