Getting Started with ObjectQL ​
ObjectQL is a universal, metadata-driven ORM designed for building dynamic business applications. Unlike traditional ORMs where you define schema in class files (like TypeORM entities), ObjectQL uses a Metadata-First approach.
Why ObjectQL? ​
- Metadata-Driven: Define your data models in JSON or YAML. Perfect for low-code platforms where schema changes at runtime.
- Universal Protocol: The query language is a JSON AST, making it easy for frontends or AI agents to generate queries.
- Action & Hook System: Built-in support for "Button Actions" (RPC) and "Triggers" (Hooks), allowing you to model Behavior alongside Data.
Installation ​
Install the core package and a driver (e.g., PostgreSQL or MongoDB).
bash
npm install @objectql/core @objectql/driver-knex knex pg
# or
npm install @objectql/core @objectql/driver-mongo mongodbQuick Start: The "Hello World" ​
Let's build a simple To-Do List backend.
1. Define Your Object ​
In ObjectQL, everything is an "Object" (like a Table or Collection).
yaml
# todo.object.yml
name: todo
label: To-Do Item
fields:
title:
type: text
label: Task Name
completed:
type: boolean
default: false2. Configure the Engine ​
Updated in v0.2: You can now use a simple connection string.
typescript
import { ObjectQL } from '@objectql/core';
import * as path from 'path';
async function main() {
const db = new ObjectQL({
// 1. Connection String (Protocol://Path)
// Detects 'sqlite', 'postgres', 'mongodb' automatically
connection: 'sqlite://data.db',
// 2. Schema Source
// Where your *.object.yml files are located
source: ['src/objects'],
// 3. Load Presets (Optional)
// Load standard objects from npm packages
presets: ['@objectql/preset-auth']
});
await db.init();
// ...
// 3. Create Data (CRUD)
// Create a context (representing a user request)
const ctx = db.createContext({});
const todoRepo = ctx.object('todo');
const newTask = await todoRepo.create({
title: 'Learn ObjectQL',
completed: false
});
console.log('Created:', newTask);
// 4. Query Data
const tasks = await todoRepo.find({
filters: [['completed', '=', false]]
});
console.log('Pending Tasks:', tasks);
}
main();Adding Business Logic ​
ObjectQL shines when you need to add logic.
Adding a Hook ​
Triggers logic automatically when data changes.
typescript
app.on('beforeCreate', 'todo', async (ctx) => {
if (ctx.doc.title === 'Sleep') {
throw new Error("Cannot sleep yet!");
}
// Auto-tagging
ctx.doc.title = `[Task] ${ctx.doc.title}`;
});Adding an Action ​
Defines a custom operation (RPC) that frontends can call.
typescript
// Define protocol
app.registerAction('todo', 'mark_done', async (ctx) => {
const { id } = ctx;
await ctx.object('todo').update(id, { completed: true });
return { message: 'Good job!' };
});
// Invocation
await ctx.object('todo').execute('mark_done', 'id_123', {});Next Steps ​
- Data Modeling: Learn about all field types (Select, Lookup, Date, etc.)
- SDK Reference: Explore the full API.
- Hooks: Deep dive into the event system.