### Install @qbobjx/sql-engine Source: https://github.com/qb-objx/objx/blob/main/packages/sql-engine/README.md Install the package using npm. ```bash npm install @qbobjx/sql-engine ``` -------------------------------- ### Install @qbobjx/plugins Source: https://github.com/qb-objx/objx/blob/main/packages/plugins/README.md Install the @qbobjx/plugins package using npm. ```bash npm install @qbobjx/plugins ``` -------------------------------- ### Install Dependencies Source: https://github.com/qb-objx/objx/blob/main/examples/express-api/README.md Run this command to install project dependencies. ```bash npm install ``` -------------------------------- ### Install @qbobjx/core Source: https://github.com/qb-objx/objx/blob/main/packages/core/README.md Install the core runtime package for OBJX using npm. ```bash npm install @qbobjx/core ``` -------------------------------- ### Install @qbobjx/postgres-driver dependencies Source: https://github.com/qb-objx/objx/blob/main/packages/postgres-driver/README.md Install the driver along with required core and SQL engine packages. ```bash npm install @qbobjx/postgres-driver @qbobjx/sql-engine @qbobjx/core pg ``` -------------------------------- ### Install OBJX dependencies Source: https://github.com/qb-objx/objx/blob/main/README.md Commands to install core packages and specific database drivers. ```bash npm install @qbobjx/core @qbobjx/sql-engine @qbobjx/sqlite-driver @qbobjx/plugins ``` ```bash npm install @qbobjx/core @qbobjx/sql-engine @qbobjx/postgres-driver @qbobjx/plugins pg ``` ```bash npm install @qbobjx/core @qbobjx/sql-engine @qbobjx/mysql-driver @qbobjx/plugins mysql2 ``` ```bash npm install -D @qbobjx/codegen ``` ```bash npm install @qbobjx/nestjs @nestjs/common @nestjs/core @nestjs/platform-express rxjs reflect-metadata ``` -------------------------------- ### Database Setup Commands Source: https://github.com/qb-objx/objx/blob/main/examples/nestjs-api/README.md Commands for managing database migrations and seeds. ```bash npm run db:setup ``` ```bash npm run db:migrate ``` ```bash npm run db:seed ``` ```bash npm run db:seed:revert ``` ```bash npm run db:migrate:down ``` -------------------------------- ### Install @qbobjx/mysql-driver dependencies Source: https://github.com/qb-objx/objx/blob/main/packages/mysql-driver/README.md Install the driver along with required peer dependencies including the SQL engine, core framework, and mysql2. ```bash npm install @qbobjx/mysql-driver @qbobjx/sql-engine @qbobjx/core mysql2 ``` -------------------------------- ### Install OBJX drivers and plugins Source: https://github.com/qb-objx/objx/blob/main/packages/nestjs/README.md Install additional drivers and plugins as required by the specific project configuration. ```bash npm install @qbobjx/core @qbobjx/sqlite-driver @qbobjx/plugins ``` -------------------------------- ### Install @qbobjx/sqlite-driver Source: https://github.com/qb-objx/objx/blob/main/packages/sqlite-driver/README.md Install the SQLite driver along with the SQL engine and core OBJX packages. ```bash npm install @qbobjx/sqlite-driver @qbobjx/sql-engine @qbobjx/core ``` -------------------------------- ### Install @qbobjx/validation Source: https://github.com/qb-objx/objx/blob/main/packages/validation/README.md Use this command to install the package via npm. ```bash npm install @qbobjx/validation ``` -------------------------------- ### NestJS Module Setup with ObjxModule Source: https://github.com/qb-objx/objx/blob/main/pages/index.html Configure the ObjxModule asynchronously in your NestJS application. This example demonstrates setting up a SQLite session with tenant scope, soft delete, and audit trail plugins, along with enabling request context. ```typescript @Module({ imports: [ ObjxModule.forRootAsync({ global: true, inject: [AuditTrailStore], useFactory: (auditTrailStore) => ({ session: createSqliteSession({ driver: createSqliteDriver({ databasePath: './data/app.sqlite', pragmas: ['foreign_keys = on'], }), executionContextManager: createExecutionContextManager(), hydrateByDefault: true, plugins: [ createTenantScopePlugin(), createSoftDeletePlugin(), createAuditTrailPlugin({ actorKey: 'actorId', emit: (entry) => auditTrailStore.append(entry), }), ], }), requestContext: { enabled: true, }, }), }), ], }) export class AppModule {} ``` -------------------------------- ### Install @qbobjx/codegen Source: https://github.com/qb-objx/objx/blob/main/packages/codegen/README.md Install the @qbobjx/codegen package as a development dependency using npm. ```bash npm install -D @qbobjx/codegen ``` -------------------------------- ### Seed File Example Source: https://context7.com/qb-objx/objx/llms.txt Populate the database with initial data using SQL 'insert' statements in the 'run' array and corresponding 'delete' statements in the 'revert' array of a seed file. ```javascript // db/seeds/000001_demo.seed.mjs export default { run: [ "insert into companies (name, tenantId) values ('OBJX Labs', 'demo');", "insert into users (email, companyId, tenantId) values ('admin@objx.dev', 1, 'demo');", "insert into projects (name, companyId, ownerId, tenantId) values ('Demo Project', 1, 1, 'demo');", ], revert: [ "delete from projects where tenantId = 'demo';", "delete from users where tenantId = 'demo';", "delete from companies where tenantId = 'demo';", ], }; ``` -------------------------------- ### Install @qbobjx/nestjs and dependencies Source: https://github.com/qb-objx/objx/blob/main/packages/nestjs/README.md Install the core integration package along with required NestJS and RxJS dependencies. ```bash npm install @qbobjx/nestjs @nestjs/common @nestjs/core rxjs ``` -------------------------------- ### Run Development Server Source: https://github.com/qb-objx/objx/blob/main/examples/express-api/README.md Execute this command to start the development server. The default address is http://127.0.0.1:3000. ```bash npm run dev ``` -------------------------------- ### Install OBJX Core Packages Source: https://context7.com/qb-objx/objx/llms.txt Install the core OBJX packages along with the SQL engine and the driver for your chosen database. Additional packages are available for plugins and codegen. ```bash # SQLite npm install @qbobjx/core @qbobjx/sql-engine @qbobjx/sqlite-driver @qbobjx/plugins # Postgres npm install @qbobjx/core @qbobjx/sql-engine @qbobjx/postgres-driver @qbobjx/plugins pg # MySQL npm install @qbobjx/core @qbobjx/sql-engine @qbobjx/mysql-driver @qbobjx/plugins mysql2 # Codegen and tooling npm install -D @qbobjx/codegen # NestJS integration npm install @qbobjx/nestjs @nestjs/common @nestjs/core @nestjs/platform-express rxjs reflect-metadata ``` -------------------------------- ### Run advanced runtime example Source: https://github.com/qb-objx/objx/blob/main/docs/getting-started.md Executes a complex end-to-end flow demonstrating relations and graph operations. ```bash node examples/complex-runtime/src/app.mjs ``` -------------------------------- ### Migration File Example Source: https://context7.com/qb-objx/objx/llms.txt Define database schema changes using SQL statements in 'run' and 'revert' arrays within a migration file. This example shows table creation and dropping for companies, users, and projects. ```javascript // db/migrations/000001_init.migration.mjs export default { run: [ `create table companies ( id integer primary key autoincrement, name text not null, tenantId text not null );`, `create table users ( id integer primary key autoincrement, email text not null, companyId integer references companies(id), tenantId text not null, deletedAt text );`, `create table projects ( id integer primary key autoincrement, companyId integer not null references companies(id), ownerId integer references users(id), name text not null, status text not null default 'planned', tenantId text not null, deletedAt text ); `, ], revert: [ 'drop table if exists projects;', 'drop table if exists users;', 'drop table if exists companies;', ], }; ``` -------------------------------- ### Example cURL Request with Headers Source: https://github.com/qb-objx/objx/blob/main/examples/express-api/README.md This cURL command demonstrates how to make a request to the API, including the required 'x-tenant-id' header. ```bash curl -H "x-tenant-id: demo" http://127.0.0.1:3000/projects ``` -------------------------------- ### Define models and execute queries in OBJX Source: https://github.com/qb-objx/objx/blob/main/README.md A minimal example demonstrating model definition with plugins and executing a query within an execution context. ```typescript import { belongsToOne, col, createExecutionContextManager, defineModel, hasMany, } from '@qbobjx/core'; import { createSqliteSession } from '@qbobjx/sqlite-driver'; import { createAuditTrailPlugin, createSoftDeletePlugin, createTenantScopePlugin, } from '@qbobjx/plugins'; const auditEntries: unknown[] = []; const Company = defineModel({ name: 'Company', table: 'companies', columns: { id: col.int().primary(), name: col.text(), tenantId: col.text(), }, plugins: [createTenantScopePlugin()], }); const User = defineModel({ name: 'User', table: 'users', columns: { id: col.int().primary(), email: col.text(), companyId: col.int().nullable(), tenantId: col.text(), deletedAt: col.timestamp().nullable(), }, relations: (user) => ({ company: belongsToOne(() => Company, { from: user.columns.companyId, to: Company.columns.id, }), }), plugins: [ createTenantScopePlugin(), createSoftDeletePlugin(), createAuditTrailPlugin({ actorKey: 'actorId', emit(entry) { auditEntries.push(entry); }, }), ], }); const Project = defineModel({ name: 'Project', table: 'projects', columns: { id: col.int().primary(), companyId: col.int(), ownerId: col.int().nullable(), name: col.text(), status: col.text(), tenantId: col.text(), deletedAt: col.timestamp().nullable(), }, relations: (project) => ({ company: belongsToOne(() => Company, { from: project.columns.companyId, to: Company.columns.id, }), owner: belongsToOne(() => User, { from: project.columns.ownerId, to: User.columns.id, }), members: hasMany(() => User, { from: project.columns.companyId, to: User.columns.companyId, }), }), plugins: [createTenantScopePlugin(), createSoftDeletePlugin()], }); const executionContextManager = createExecutionContextManager(); const session = createSqliteSession({ databasePath: './app.sqlite', executionContextManager, hydrateByDefault: true, pragmas: ['foreign_keys = on'], }); const rows = await executionContextManager.run( { values: { tenantId: 'tenant_a', actorId: 'user_admin', }, }, () => session.execute( Project.query() .where(({ status }, op) => op.eq(status, 'active')) .withRelated({ company: true, owner: true, }), ), ); console.log(rows); ``` -------------------------------- ### Attach Query Observers to Session Source: https://github.com/qb-objx/objx/blob/main/README.md Configures a session with query observers to log query lifecycle events (start, success, error). Requires `createSqliteSession`. ```typescript const session = createSqliteSession({ databasePath: './app.sqlite', observers: [ { onQueryStart(event) { console.log('sql:start', event.compiledQuery.sql); }, onQuerySuccess(event) { console.log('sql:ok', event.durationMs); }, onQueryError(event) { console.error('sql:error', event.error); }, }, ], }); ``` -------------------------------- ### Generate a starter template Source: https://github.com/qb-objx/objx/blob/main/docs/getting-started.md Creates a boilerplate SQLite service structure. ```bash npm run codegen -- template --template sqlite-starter --out ./starter --package-name my-objx-app ``` -------------------------------- ### Generate migration and seed schemas Source: https://github.com/qb-objx/objx/blob/main/docs/getting-started.md Creates starter files for database migrations and seeding. ```bash npm run codegen -- template --template migration-seed-schemas --out ./db ``` -------------------------------- ### View @qbobjx/codegen CLI Help Source: https://github.com/qb-objx/objx/blob/main/packages/codegen/README.md Run the objx-codegen CLI with the --help flag to see available commands and options. ```bash npx objx-codegen --help ``` -------------------------------- ### Build the project Source: https://github.com/qb-objx/objx/blob/main/examples/benchmarks/README.md Compiles the project before running benchmarks. ```bash npm run build ``` -------------------------------- ### Graph Operations with OBJX Source: https://context7.com/qb-objx/objx/llms.txt Insert or upsert entire object graphs including nested relations in a single operation. OBJX automatically handles foreign key resolution and relation linking. Use `hydrate: true` to get hydrated results. ```typescript // Insert a complete object graph const project = await session.insertGraph( Project, { name: 'Core Runtime', status: 'planned', company: { name: 'OBJX Labs', tenantId: 'tenant_a', }, owner: { email: 'owner@objx.dev', tenantId: 'tenant_a', }, tasks: [ { title: 'Design query planner', status: 'todo', tenantId: 'tenant_a', assignee: { email: 'platform@objx.dev', tenantId: 'tenant_a', }, comments: [ { body: 'Kickoff with architecture review.', tenantId: 'tenant_a', author: { email: 'lead@objx.dev', tenantId: 'tenant_a', }, }, ], }, ], tenantId: 'tenant_a', }, { hydrate: true, }, ); console.log(project.id); // Auto-generated ID console.log(project.company.id); // Nested company ID console.log(project.tasks[0].id); // Nested task ID // Upsert existing graph (update existing, insert new) const updated = await session.upsertGraph( Project, { id: 1, // Existing project status: 'in_progress', tasks: [ { id: 10, title: 'Typed planner' }, // Update existing task { title: 'Private beta' }, // Insert new task ], }, { hydrate: true, }, ); ``` -------------------------------- ### Run default benchmarks Source: https://github.com/qb-objx/objx/blob/main/examples/benchmarks/README.md Executes the benchmark suite using default settings and all official drivers. ```bash npm run benchmark ``` -------------------------------- ### Codegen CLI: Generate SQLite Starter Project Source: https://context7.com/qb-objx/objx/llms.txt Create a starter project for a SQLite database application using the Codegen CLI. This command scaffolds a basic project structure with necessary configurations. ```bash npm run codegen -- template \ --template sqlite-starter \ --out ./starter \ --package-name my-objx-app ``` -------------------------------- ### Create SQLite Session with @qbobjx/sqlite-driver Source: https://github.com/qb-objx/objx/blob/main/packages/sqlite-driver/README.md Import and create a new SQLite session using the provided database path. ```typescript import { createSqliteSession } from '@qbobjx/sqlite-driver'; const session = createSqliteSession({ databasePath: './app.sqlite', }); ``` -------------------------------- ### Create Project with Tasks Source: https://github.com/qb-objx/objx/blob/main/examples/express-api/README.md Use this cURL command to create a new project along with its associated tasks. It includes 'content-type', 'x-tenant-id', and 'x-actor-id' headers, and a JSON payload. ```bash curl -X POST http://127.0.0.1:3000/projects \ -H "content-type: application/json" \ -H "x-tenant-id: demo" \ -H "x-actor-id: cli" \ -d '{ "name": "Launch API", "status": "planned", "tasks": [ { "title": "Ship CRUD", "status": "doing" }, { "title": "Write docs", "status": "todo" } ] }' ``` -------------------------------- ### Quick Usage of sql-engine Source: https://github.com/qb-objx/objx/blob/main/packages/sql-engine/README.md Demonstrates basic usage of the sql-engine for creating SQL queries with identifiers. ```typescript import { identifier, sql } from '@qbobjx/sql-engine'; const query = sql`select * from ${identifier('projects')}`; ``` -------------------------------- ### Initialize MySQL session Source: https://github.com/qb-objx/objx/blob/main/packages/mysql-driver/README.md Create a database pool using mysql2 and initialize the OBJX MySQL session. ```ts import mysql from 'mysql2/promise'; import { createMySqlSession } from '@qbobjx/mysql-driver'; const pool = mysql.createPool({ uri: process.env.DATABASE_URL }); const session = createMySqlSession({ pool }); ``` -------------------------------- ### Execute Objx CLI Commands Source: https://github.com/qb-objx/objx/blob/main/pages/index.html Commands for scaffolding schemas, running migrations, and executing seeds against a database. ```bash npm run codegen -- template --template migration-seed-schemas --out ./db ``` ```bash npm run codegen -- migrate --dialect postgres --database "$DATABASE_URL" --dir ./db/migrations --direction up ``` ```bash npm run codegen -- seed --dialect postgres --database "$DATABASE_URL" --dir ./db/seeds --direction run ``` -------------------------------- ### Create Project with Tasks via cURL Source: https://github.com/qb-objx/objx/blob/main/examples/nestjs-api/README.md Send a POST request to create a project including nested tasks. ```bash curl -X POST http://127.0.0.1:3001/projects \ -H "content-type: application/json" \ -H "x-tenant-id: demo" \ -H "x-actor-id: cli" \ -d '{ "name": "Build Nest API", "status": "planned", "tasks": [ { "title": "Wire providers", "status": "doing" }, { "title": "Ship controller", "status": "todo" } ] }' ``` -------------------------------- ### List Projects via cURL Source: https://github.com/qb-objx/objx/blob/main/examples/nestjs-api/README.md Retrieve seeded projects using the required tenant header. ```bash curl -H "x-tenant-id: demo" http://127.0.0.1:3001/projects ``` -------------------------------- ### Implement Express REST API with OBJX Source: https://context7.com/qb-objx/objx/llms.txt Sets up an Express server with tenant-aware middleware and CRUD endpoints for a Project resource. ```javascript import express from 'express'; import { createExecutionContextManager } from '@qbobjx/core'; import { createSqliteSession } from '@qbobjx/sqlite-driver'; import { ObjxValidationError } from '@qbobjx/validation'; const app = express(); app.use(express.json()); const executionContextManager = createExecutionContextManager(); const session = createSqliteSession({ databasePath: './app.sqlite', executionContextManager, hydrateByDefault: true, }); // Tenant context middleware app.use((req, res, next) => { const tenantId = req.header('x-tenant-id'); if (!tenantId) { return res.status(400).json({ error: 'missing_tenant_id' }); } executionContextManager.run( { values: { tenantId, actorId: req.header('x-actor-id') ?? 'anonymous', }, }, next, ); }); // List projects app.get('/projects', async (req, res) => { const rows = await session.execute( Project.query() .withRelated({ tasks: true }) .orderBy(({ id }) => id, 'desc'), ); res.json({ data: rows }); }); // Get single project app.get('/projects/:id', async (req, res) => { const rows = await session.execute( Project.query() .where(({ id }, op) => op.eq(id, parseInt(req.params.id))) .withRelated({ tasks: true }), ); if (rows.length === 0) { return res.status(404).json({ error: 'project_not_found' }); } res.json({ data: rows[0] }); }); // Create project with nested tasks app.post('/projects', async (req, res) => { const inserted = await session.insertGraph( Project, { name: req.body.name, status: req.body.status ?? 'planned', tasks: req.body.tasks?.map(t => ({ title: t.title, status: t.status ?? 'todo', })), }, { hydrate: true }, ); res.status(201).json({ data: inserted }); }); // Update project app.patch('/projects/:id', async (req, res) => { const updated = await session.execute( Project.update({ name: req.body.name, status: req.body.status }) .where(({ id }, op) => op.eq(id, parseInt(req.params.id))) .returning(({ id }) => [id]), ); if (updated.length === 0) { return res.status(404).json({ error: 'project_not_found' }); } res.json({ data: updated[0] }); }); // Delete project (soft delete) app.delete('/projects/:id', async (req, res) => { const count = await session.execute( Project.delete().where(({ id }, op) => op.eq(id, parseInt(req.params.id))), ); if (count === 0) { return res.status(404).json({ error: 'project_not_found' }); } res.status(204).end(); }); // Validation error handler app.use((error, req, res, next) => { if (error instanceof ObjxValidationError) { return res.status(422).json({ error: 'validation_failed', message: error.message, issues: error.issues, }); } next(error); }); app.listen(3000); ``` -------------------------------- ### Database Session Initialization Source: https://context7.com/qb-objx/objx/llms.txt Methods to create database sessions for different drivers, supporting configuration for paths, connection pools, execution context managers, and query observers. ```APIDOC ## createSqliteSession / createPostgresSession / createMySqlSession ### Description Creates a database session factory configured for a specific database driver (SQLite, Postgres, or MySQL) to handle query execution and transactions. ### Parameters - **options** (object) - Required - Configuration object containing driver-specific settings (e.g., databasePath, pool, hydrateByDefault, executionContextManager, observers). ### Request Example // SQLite example const sqliteSession = createSqliteSession({ databasePath: './app.sqlite', pragmas: ['foreign_keys = on'], hydrateByDefault: true }); ``` -------------------------------- ### Create Database Sessions for SQLite, PostgreSQL, and MySQL Source: https://context7.com/qb-objx/objx/llms.txt Initialize database sessions for different database systems. Sessions can be configured with specific options like database path, pragmas, execution context managers, and query observers. ```typescript import { createExecutionContextManager } from '@qbobjx/core'; import { createSqliteSession } from '@qbobjx/sqlite-driver'; import { createPostgresSession } from '@qbobjx/postgres-driver'; import { createMySqlSession } from '@qbobjx/mysql-driver'; import { DatabaseSync } from 'node:sqlite'; import { Pool } from 'pg'; import mysql from 'mysql2/promise'; // SQLite session with path const sqliteSession = createSqliteSession({ databasePath: './app.sqlite', pragmas: ['foreign_keys = on'], hydrateByDefault: true, }); // SQLite session with custom DatabaseSync const database = new DatabaseSync('./app.sqlite'); const sqliteSessionCustom = createSqliteSession({ database, hydrateByDefault: true, }); // Postgres session with pool const pgPool = new Pool({ connectionString: process.env.DATABASE_URL, }); const postgresSession = createPostgresSession({ pool: pgPool, hydrateByDefault: true, }); // MySQL session with pool const mysqlPool = mysql.createPool({ uri: process.env.DATABASE_URL, }); const mysqlSession = createMySqlSession({ pool: mysqlPool, hydrateByDefault: true, }); // Session with execution context manager for tenant/actor scoping const executionContextManager = createExecutionContextManager(); const sessionWithContext = createSqliteSession({ databasePath: './app.sqlite', executionContextManager, hydrateByDefault: true, pragmas: ['foreign_keys = on'], }); // Session with query observers for logging/tracing const sessionWithObservers = createSqliteSession({ databasePath: './app.sqlite', observers: [ { onQueryStart(event) { console.log('sql:start', event.compiledQuery.sql); }, onQuerySuccess(event) { console.log('sql:ok', event.durationMs); }, onQueryError(event) { console.error('sql:error', event.error); }, }, ], }); ``` -------------------------------- ### Execute Raw SQL with Helpers Source: https://context7.com/qb-objx/objx/llms.txt Provides utilities for safe parameter binding, identifier escaping, and SQL fragment composition. ```typescript import { identifier, sql, ref, joinSql } from '@qbobjx/sql-engine'; // Basic raw SQL with parameters const result = await session.execute( sql`select * from projects where status = ${'active'}`, ); // Safe identifier escaping const countResult = await session.execute( sql`select count(*) as ${identifier('totalProjects')} from ${identifier('projects')}`, ); console.log(countResult.rows[0]?.totalProjects); // Multi-part identifiers (table.column) const query = sql` select * from ${identifier('projects')} where ${identifier('projects', 'status')} = ${'active'} `; // Column references const compiled = session.compile( Project.query().where(({ createdAt }, op) => op.isNotNull(createdAt)), ); console.log(compiled.sql); console.log(ref('projects.createdAt')); // Join multiple SQL fragments const conditions = [ sql`status = ${'active'}`, sql`name like ${'%test%'}`, ]; const whereClause = joinSql(conditions, sql` and `); ``` -------------------------------- ### Configure MySQL Connection Source: https://github.com/qb-objx/objx/blob/main/README.md Initialize a MySQL session using a mysql2/promise pool or client. ```typescript import mysql from 'mysql2/promise'; import { createMySqlSession } from '@qbobjx/mysql-driver'; const pool = mysql.createPool({ uri: process.env.DATABASE_URL, }); const session = createMySqlSession({ pool, hydrateByDefault: true, }); ``` -------------------------------- ### Configure Postgres Connection Source: https://github.com/qb-objx/objx/blob/main/README.md Initialize a Postgres session using a pg pool or client. ```typescript import { Pool } from 'pg'; import { createPostgresSession } from '@qbobjx/postgres-driver'; const pool = new Pool({ connectionString: process.env.DATABASE_URL, }); const session = createPostgresSession({ pool, hydrateByDefault: true, }); ``` -------------------------------- ### Run selected drivers Source: https://github.com/qb-objx/objx/blob/main/examples/benchmarks/README.md Limits the benchmark execution to specific database drivers. ```bash node examples/benchmarks/src/run.mjs --drivers sqlite ``` ```bash node examples/benchmarks/src/run.mjs --drivers postgres,mysql ``` -------------------------------- ### Initialize Postgres session Source: https://github.com/qb-objx/objx/blob/main/packages/postgres-driver/README.md Configure a connection pool and create a session instance for database operations. ```ts import { Pool } from 'pg'; import { createPostgresSession } from '@qbobjx/postgres-driver'; const pool = new Pool({ connectionString: process.env.DATABASE_URL }); const session = createPostgresSession({ pool }); ``` -------------------------------- ### Run custom benchmark workload Source: https://github.com/qb-objx/objx/blob/main/examples/benchmarks/README.md Executes a custom benchmark run with specified parameters for dataset size, warmup, and iterations. ```bash node examples/benchmarks/src/run.mjs --people 5000 --pets-per-person 4 --warmup 150 --iterations 1500 ``` -------------------------------- ### Run database seeds Source: https://github.com/qb-objx/objx/blob/main/docs/getting-started.md Executes seed scripts to populate the database. ```bash npm run codegen -- seed --dialect sqlite3 --database ./app.sqlite --dir ./db/seeds --direction run ``` -------------------------------- ### Execute SELECT Query with Filtering, Ordering, and Pagination Source: https://context7.com/qb-objx/objx/llms.txt Run a SELECT query to retrieve data, applying filters, sorting, and pagination. Ensure the 'Project' model and 'session' object are properly defined. ```typescript import { identifier, sql } from '@qbobjx/sql-engine'; // SELECT query with filtering, ordering, and pagination const projects = await session.execute( Project.query() .select(({ id, name, status }) => [id, name, status]) .where(({ status }, op) => op.eq(status, 'active')) .orderBy(({ id }) => id, 'desc') .limit(20) .offset(0), ); // Composed predicates with AND/OR const rows = await session.execute( Project.query().where(({ id, status, ownerId }, op) => op.and( op.or(op.eq(id, 1), op.eq(status, 'planned')), op.isNotNull(ownerId), ), ), ); // INSERT with returning clause const inserted = await session.execute( Project.insert({ companyId: 1, ownerId: 2, name: 'OBJX', status: 'planned', tenantId: 'tenant_a', }).returning(({ id, name, status }) => [id, name, status]), { hydrate: true }, ); // UPDATE returning affected row count const count = await session.execute( Project.update({ status: 'active' }).where(({ id }, op) => op.eq(id, 1)), ); // UPDATE with returning clause const updated = await session.execute( Project.update({ status: 'active' }) .where(({ id }, op) => op.eq(id, 1)) .returning(({ id, status }) => [id, status]), { hydrate: true }, ); // DELETE (soft delete if plugin is configured) const deletedCount = await session.execute( Project.delete().where(({ id }, op) => op.eq(id, 1)), ); // Hard delete bypassing soft delete plugin await session.execute( Project.delete().hardDelete().where(({ id }, op) => op.eq(id, 1)), ); // Raw SQL execution const result = await session.execute( sql`select count(*) as ${identifier('totalProjects')} from ${identifier('projects')}`, ); console.log(result.rows[0]?.totalProjects); ``` -------------------------------- ### Enable Hydration by Default Source: https://github.com/qb-objx/objx/blob/main/README.md Configures the session to hydrate all queries by default. Use `createSqliteSession` or similar factory functions. ```typescript const session = createSqliteSession({ databasePath: './app.sqlite', hydrateByDefault: true, }); ``` -------------------------------- ### Define a Model with @qbobjx/core Source: https://github.com/qb-objx/objx/blob/main/packages/core/README.md Quickly define a data model, including table name, columns, and their types, using the defineModel function from @qbobjx/core. Ensure necessary imports are included. ```typescript import { col, defineModel } from '@qbobjx/core'; export const Project = defineModel({ table: 'projects', columns: { id: col.int().primary(), name: col.text(), tenantId: col.text().generated(), }, }); ``` -------------------------------- ### Codegen CLI: Run Database Seeds Source: https://context7.com/qb-objx/objx/llms.txt Execute seed files to populate the database with initial or demo data. This command runs the 'run' SQL statements defined in the seed files. ```bash npm run codegen -- seed \ --dialect sqlite3 \ --database ./app.sqlite \ --dir ./db/seeds \ --direction run ``` -------------------------------- ### Configure SQLite Connection Source: https://github.com/qb-objx/objx/blob/main/README.md Connect to SQLite using either a file path or an existing DatabaseSync instance. ```typescript import { createSqliteSession } from '@qbobjx/sqlite-driver'; const session = createSqliteSession({ databasePath: './app.sqlite', pragmas: ['foreign_keys = on'], hydrateByDefault: true, }); ``` ```typescript import { DatabaseSync } from 'node:sqlite'; import { createSqliteSession } from '@qbobjx/sqlite-driver'; const database = new DatabaseSync('./app.sqlite'); const session = createSqliteSession({ database, hydrateByDefault: true, }); ``` -------------------------------- ### Codegen CLI: Generate Migration and Seed Schemas Source: https://context7.com/qb-objx/objx/llms.txt Generate template files for database migrations and seeds using the Codegen CLI. These templates provide a structure for defining database schema changes and initial data. ```bash npm run codegen -- template \ --template migration-seed-schemas \ --out ./db ``` -------------------------------- ### Apply database migrations Source: https://github.com/qb-objx/objx/blob/main/docs/getting-started.md Applies pending migrations to the specified SQLite database. ```bash npm run codegen -- migrate --dialect sqlite3 --database ./app.sqlite --dir ./db/migrations --direction up ``` -------------------------------- ### Query Including Deleted Rows Source: https://github.com/qb-objx/objx/blob/main/examples/express-api/README.md Fetch projects, including those that have been soft-deleted, by appending the 'deleted=include' query parameter to the request URL. Requires the 'x-tenant-id' header. ```bash curl -H "x-tenant-id: demo" \ "http://127.0.0.1:3000/projects?deleted=include" ``` -------------------------------- ### Codegen CLI: Run Database Migrations Up Source: https://context7.com/qb-objx/objx/llms.txt Apply database migrations to update the schema to the latest version. This command executes SQL statements defined in the migration files. ```bash npm run codegen -- migrate \ --dialect sqlite3 \ --database ./app.sqlite \ --dir ./db/migrations \ --direction up ``` -------------------------------- ### Raw SQL Helpers Source: https://context7.com/qb-objx/objx/llms.txt Utilities for executing raw SQL queries with safe parameter binding and identifier escaping. ```APIDOC ## Raw SQL Helpers ### Description Provides functions for safe SQL construction, including parameter binding, identifier escaping, and SQL fragment joining. ### Functions - **sql** - Tagged template literal for creating safe SQL queries with parameter binding. - **identifier** - Escapes table or column names to prevent SQL injection. - **ref** - Creates a reference to a specific table column. - **joinSql** - Joins multiple SQL fragments with a separator. ``` -------------------------------- ### Compile Query and Use References Source: https://github.com/qb-objx/objx/blob/main/README.md Compiles a query to SQL and demonstrates using `ref` for referencing columns. Useful for debugging or complex query construction. ```typescript import { ref } from '@qbobjx/sql-engine'; const compiled = session.compile( Project.query().where(({ createdAt }, op) => op.isNotNull(createdAt)), ); console.log(compiled.sql); console.log(ref('projects.createdAt')); ``` -------------------------------- ### Create Tenant Scope Plugin Source: https://context7.com/qb-objx/objx/llms.txt Automatically filters all queries by tenant ID from the execution context, ensuring data isolation between tenants. Configure the column, context key, and bypass key as needed. ```typescript import { createTenantScopePlugin } from '@qbobjx/plugins'; const Project = defineModel({ table: 'projects', columns: { id: col.int().primary(), name: col.text(), tenantId: col.text(), }, plugins: [ createTenantScopePlugin({ column: 'tenantId', // Column name (default: 'tenantId') contextKey: 'tenantId', // Execution context key (default: 'tenantId') bypassKey: 'objx.tenantScope.bypass', // Key to bypass filter required: true, // Require tenant in context }), ], }); // All queries automatically filtered by tenant await executionContextManager.run( { values: { tenantId: 'tenant_a' } }, async () => { // Only returns tenant_a projects const projects = await session.execute(Project.query()); // Inserts automatically include tenantId await session.execute( Project.insert({ name: 'New Project' }), ); }, ); // Cross-tenant query with bypass await executionContextManager.run( { values: { 'objx.tenantScope.bypass': true } }, () => session.execute(Project.query()), ); ``` -------------------------------- ### Plan relation joins Source: https://github.com/qb-objx/objx/blob/main/README.md Compiles a query with joins to inspect the resulting SQL and parameters. ```ts const compiled = session.compile( Project.query().joinRelated({ owner: true, tasks: { assignee: true, }, }), ); console.log(compiled.sql); console.log(compiled.parameters); ``` -------------------------------- ### Generate OBJX models Source: https://github.com/qb-objx/objx/blob/main/docs/getting-started.md Converts an introspection snapshot into usable OBJX models. ```bash npm run codegen -- generate --input ./generated/schema.json --out ./generated/models ``` -------------------------------- ### Quick Usage of Soft Delete Plugin Source: https://github.com/qb-objx/objx/blob/main/packages/plugins/README.md Import and create the soft delete plugin for use with OBJX. Ensure the plugin is added to the plugins array. ```typescript import { createSoftDeletePlugin } from '@qbobjx/plugins'; const plugins = [createSoftDeletePlugin()]; ``` -------------------------------- ### session.execute Source: https://context7.com/qb-objx/objx/llms.txt Executes typed queries, raw SQL, or compiled queries through an established session. ```APIDOC ## session.execute ### Description Executes a query object or raw SQL string against the database session. Returns typed results based on the query builder configuration. ### Parameters - **query** (object/sql) - Required - The query builder object or raw SQL template. - **options** (object) - Optional - Execution options such as { hydrate: boolean }. ### Request Example // SELECT query example const projects = await session.execute( Project.query() .select(({ id, name, status }) => [id, name, status]) .where(({ status }, op) => op.eq(status, 'active')) .limit(20) ); ``` -------------------------------- ### Soft Delete Project Source: https://github.com/qb-objx/objx/blob/main/examples/express-api/README.md Perform a soft delete on a project by sending a DELETE request with the 'x-tenant-id' and 'x-actor-id' headers. ```bash curl -X DELETE \ -H "x-tenant-id: demo" \ -H "x-actor-id: cli" \ http://127.0.0.1:3000/projects/1 ``` -------------------------------- ### Select records with query builder Source: https://github.com/qb-objx/objx/blob/main/README.md Executes a select query with filtering, ordering, and pagination. ```ts const projects = await session.execute( Project.query() .select(({ id, name, status }) => [id, name, status]) .where(({ status }, op) => op.eq(status, 'active')) .orderBy(({ id }) => id, 'desc') .limit(20) .offset(0), ); ``` -------------------------------- ### Execute Raw SQL with Identifiers Source: https://github.com/qb-objx/objx/blob/main/README.md Executes a raw SQL query using the `sql` and `identifier` helpers for safe string interpolation. Imports are required. ```typescript import { identifier, sql } from '@qbobjx/sql-engine'; const result = await session.execute( sql`select count(*) as ${identifier('totalProjects')} from ${identifier('projects')}`, ); console.log(result.rows[0]?.totalProjects); ``` -------------------------------- ### Complete Project Transactionally Source: https://github.com/qb-objx/objx/blob/main/examples/express-api/README.md This cURL command completes a project by sending a POST request to the project's completion endpoint. It demonstrates transactional behavior and requires 'x-tenant-id' and 'x-actor-id' headers. ```bash curl -X POST \ -H "x-tenant-id: demo" \ -H "x-actor-id: cli" \ http://127.0.0.1:3000/projects/1/complete ``` -------------------------------- ### Define Model with Official Plugins Source: https://github.com/qb-objx/objx/blob/main/README.md Attaches multiple official plugins to a model definition. Ensure necessary plugins are imported before use. ```typescript import { createAuditTrailPlugin, createSoftDeletePlugin, createTenantScopePlugin, createTimestampsPlugin, } from '@qbobjx/plugins'; const auditEntries: unknown[] = []; const Article = defineModel({ table: 'articles', columns: { id: col.int().primary(), title: col.text(), tenantId: col.text(), createdAt: col.timestamp(), updatedAt: col.timestamp(), deletedAt: col.timestamp().nullable(), }, plugins: [ createTimestampsPlugin(), createTenantScopePlugin(), createSoftDeletePlugin(), createAuditTrailPlugin({ actorKey: 'actorId', emit(entry) { auditEntries.push(entry); }, }), ], }); ``` -------------------------------- ### Create Execution Context Manager Source: https://context7.com/qb-objx/objx/llms.txt Manages execution context for tenant isolation, actor tracking, tracing, and ambient transactions using AsyncLocalStorage. Use this to scope operations and manage contextual data. ```typescript import { createExecutionContextManager } from '@qbobjx/core'; const executionContextManager = createExecutionContextManager(); // Create session with context manager const session = createSqliteSession({ databasePath: './app.sqlite', executionContextManager, hydrateByDefault: true, }); // Run queries within execution context const rows = await executionContextManager.run( { values: { tenantId: 'tenant_a', actorId: 'user_123', requestId: 'req_001', }, }, async () => { // Queries automatically scoped to tenant_a return session.execute(Project.query()); }, ); // Bypass tenant scope for cross-tenant operations const allProjects = await executionContextManager.run( { values: { 'objx.tenantScope.bypass': true, }, }, () => session.execute(Project.query().withSoftDeleted()), ); // Express middleware integration app.use((req, res, next) => { const tenantId = req.header('x-tenant-id'); const actorId = req.header('x-actor-id') ?? 'anonymous'; executionContextManager.run( { values: { tenantId, actorId, }, }, next, ); }); ``` -------------------------------- ### createTimestampsPlugin Source: https://context7.com/qb-objx/objx/llms.txt Configures a plugin to automatically manage createdAt and updatedAt timestamps on model records. ```APIDOC ## createTimestampsPlugin ### Description Automatically populates and updates timestamp columns on model records. ### Configuration - **createdAt** (string) - Optional - Column name for creation timestamp (default: 'createdAt'). - **updatedAt** (string) - Optional - Column name for update timestamp (default: 'updatedAt'). ``` -------------------------------- ### Manage Timestamps with createTimestampsPlugin Source: https://context7.com/qb-objx/objx/llms.txt Automatically populates createdAt and updatedAt columns on model instances. ```typescript import { createTimestampsPlugin } from '@qbobjx/plugins'; const Article = defineModel({ table: 'articles', columns: { id: col.int().primary(), title: col.text(), createdAt: col.timestamp(), updatedAt: col.timestamp(), }, plugins: [ createTimestampsPlugin({ createdAt: 'createdAt', // Column name (default: 'createdAt') updatedAt: 'updatedAt', // Column name (default: 'updatedAt') }), ], }); ``` -------------------------------- ### Implement Audit Logging with createAuditTrailPlugin Source: https://context7.com/qb-objx/objx/llms.txt Configures audit logging for model operations with actor tracking. Requires an execution context to capture actor information. ```typescript import { createAuditTrailPlugin, type AuditTrailEntry } from '@qbobjx/plugins'; const auditEntries: AuditTrailEntry[] = []; const Project = defineModel({ table: 'projects', columns: { id: col.int().primary(), name: col.text(), tenantId: col.text(), }, plugins: [ createAuditTrailPlugin({ actorKey: 'actorId', // Context key for actor operations: ['insert', 'update', 'delete'], // Operations to audit includeResult: false, // Include query result in entry emit(entry) { // Entry contains: at, model, table, operation, actorId, rowCount auditEntries.push(entry); console.log(`[AUDIT] ${entry.operation} on ${entry.table} by ${entry.actorId}`); }, }), ], }); // Operations are automatically audited await executionContextManager.run( { values: { tenantId: 'tenant_a', actorId: 'user_admin' } }, async () => { await session.execute( Project.insert({ name: 'New Project' }), ); // Audit entry emitted: { operation: 'insert', actorId: 'user_admin', ... } }, ); // Audit entry structure interface AuditTrailEntry { at: Date; model: string; table: string; operation: 'insert' | 'update' | 'delete' | 'select'; actorId?: unknown; actorKey: string; rowCount?: number; executionContextId?: string; transactionId?: string; result?: unknown; } ``` -------------------------------- ### Introspect SQLite Database Source: https://github.com/qb-objx/objx/blob/main/README.md Uses the codegen CLI to introspect a SQLite database and output schema information to a JSON file. Requires build and codegen scripts. ```bash npm run build npm run codegen -- introspect --dialect sqlite3 --database ./app.sqlite --out ./generated/schema.json ``` -------------------------------- ### Define Models with OBJX Source: https://github.com/qb-objx/objx/blob/main/pages/index.html Use defineModel to create typed models with columns, defaults, and relation metadata. ```typescript import { col, defineModel, hasMany } from '@qbobjx/core'; const generateSnowflakeId = () => BigInt(Date.now()); export const Project = defineModel({ name: 'Project', table: 'projects', columns: { id: col.bigInt().primary().default(() => generateSnowflakeId()), tenantId: col.text().generated(), name: col.text(), status: col.text().default('planned'), deletedAt: col.timestamp().nullable(), }, relations: (project) => ({ tasks: hasMany(() => Task, { from: project.columns.id, to: Task.columns.projectId, }), }), }); ``` -------------------------------- ### Configure ObjxModule in AppModule Source: https://github.com/qb-objx/objx/blob/main/packages/nestjs/README.md Register the OBJX module globally using forRootAsync to provide session configuration. ```typescript import { Module } from '@nestjs/common'; import { ObjxModule } from '@qbobjx/nestjs'; @Module({ imports: [ ObjxModule.forRootAsync({ global: true, useFactory: async () => ({ session: createSessionSomehow(), }), }), ], }) export class AppModule {} ``` -------------------------------- ### Codegen CLI: Revert Database Seeds Source: https://context7.com/qb-objx/objx/llms.txt Revert the database seeds by executing the 'revert' SQL statements defined in the seed files. This is useful for cleaning up seeded data. ```bash npm run codegen -- seed \ --dialect sqlite3 \ --database ./app.sqlite \ --dir ./db/seeds \ --direction revert ``` -------------------------------- ### Introspect a SQLite database Source: https://github.com/qb-objx/objx/blob/main/docs/getting-started.md Generates an introspection snapshot from a SQLite database file. ```bash npm run codegen -- introspect --dialect sqlite3 --database ./app.sqlite --out ./generated/schema.json ``` -------------------------------- ### Codegen CLI: Run Database Migrations Down Source: https://context7.com/qb-objx/objx/llms.txt Revert a specified number of database migrations. This command is useful for rolling back schema changes. ```bash npm run codegen -- migrate \ --dialect sqlite3 \ --database ./app.sqlite \ --dir ./db/migrations \ --direction down \ --steps 1 ``` -------------------------------- ### Define a Model with Columns Source: https://github.com/qb-objx/objx/blob/main/README.md Use defineModel to structure your database tables with typed columns and default values. ```typescript import { col, defineModel } from '@qbobjx/core'; export const Task = defineModel({ name: 'Task', table: 'tasks', columns: { id: col.int().primary(), title: col.text(), done: col.boolean().default(false), snowflakeId: col.bigInt().default(() => 9007199254740993n), metadata: col.json<{ priority: 'low' | 'high' }>().nullable(), createdAt: col.timestamp(), }, }); ```