An SQL-friendly ORM for Node.js built on Knex.js with powerful query building, relationship handling, and JSON Schema validation
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Core model functionality for defining database entities, validation, and basic CRUD operations.
Base class for creating database models with validation, relationships, and query capabilities.
/**
* Base Model class for database entities
*/
class Model {
// Static configuration properties
static get tableName(): string;
static get idColumn(): string | string[];
static get jsonSchema(): object;
static get relationMappings(): object;
static get jsonAttributes(): string[];
static get virtualAttributes(): string[];
static get modifiers(): object;
// Static query methods
static query(trx?: Transaction): QueryBuilder;
static relatedQuery(relationName: string, trx?: Transaction): QueryBuilder;
// Static factory methods
static fromJson(json: object, options?: ModelOptions): Model;
static fromDatabaseJson(json: object): Model;
// Static transaction methods
static transaction<T>(callback: (trx: Transaction) => Promise<T>): Promise<T>;
static bindKnex(knex: Knex): typeof Model;
// Instance methods
$id(id?: any): any;
$query(trx?: Transaction): QueryBuilder;
$relatedQuery(relationName: string, trx?: Transaction): QueryBuilder;
// JSON conversion
$toJson(options?: ToJsonOptions): object;
$toDatabaseJson(): object;
$setJson(json: object, options?: ModelOptions): this;
$setDatabaseJson(json: object): this;
// Validation
$validate(json?: object, options?: ModelOptions): object;
$beforeValidate(jsonSchema: object, json: object, options: ModelOptions): object;
$afterValidate(json: object, options: ModelOptions): void;
// Relations
$fetchGraph(expression: RelationExpression, options?: FetchGraphOptions): Promise<this>;
$setRelated(relation: string, related: Model | Model[]): this;
$appendRelated(relation: string, related: Model | Model[]): this;
// Lifecycle hooks
$beforeInsert(queryContext: QueryContext): Promise<void> | void;
$afterInsert(queryContext: QueryContext): Promise<void> | void;
$beforeUpdate(options: ModelOptions, queryContext: QueryContext): Promise<void> | void;
$afterUpdate(options: ModelOptions, queryContext: QueryContext): Promise<void> | void;
$beforeDelete(queryContext: QueryContext): Promise<void> | void;
$afterDelete(queryContext: QueryContext): Promise<void> | void;
// Utility methods
$clone(options?: CloneOptions): this;
$traverse(traverser: TraverserFunction): this;
$knex(): Knex;
}Usage Examples:
const { Model } = require('objection');
// Define a model
class Person extends Model {
static get tableName() {
return 'persons';
}
static get idColumn() {
return 'id';
}
static get jsonSchema() {
return {
type: 'object',
required: ['firstName', 'lastName'],
properties: {
id: { type: 'integer' },
firstName: { type: 'string', minLength: 1, maxLength: 255 },
lastName: { type: 'string', minLength: 1, maxLength: 255 },
age: { type: 'integer', minimum: 0, maximum: 200 },
email: { type: 'string', format: 'email' }
}
};
}
static get relationMappings() {
return {
pets: {
relation: Model.HasManyRelation,
modelClass: Pet,
join: {
from: 'persons.id',
to: 'pets.ownerId'
}
}
};
}
// Instance methods
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
// Create instances
const person = Person.fromJson({
firstName: 'John',
lastName: 'Doe',
age: 25
});
// Validate
const validated = person.$validate();Methods for creating query builders at the model class level.
/**
* Create a QueryBuilder for this model
* @param trx - Optional transaction or knex instance
* @returns QueryBuilder instance
*/
static query(trx?: Transaction): QueryBuilder;
/**
* Create a QueryBuilder for a related model
* @param relationName - Name of the relation
* @param trx - Optional transaction or knex instance
* @returns QueryBuilder instance
*/
static relatedQuery(relationName: string, trx?: Transaction): QueryBuilder;Methods for creating query builders at the model instance level.
/**
* Create a QueryBuilder for this model instance
* @param trx - Optional transaction or knex instance
* @returns QueryBuilder instance
*/
$query(trx?: Transaction): QueryBuilder;
/**
* Create a QueryBuilder for a related model of this instance
* @param relationName - Name of the relation
* @param trx - Optional transaction or knex instance
* @returns QueryBuilder instance
*/
$relatedQuery(relationName: string, trx?: Transaction): QueryBuilder;Methods for converting between JSON and model instances.
/**
* Convert model to JSON object
* @param options - Conversion options
* @returns Plain object representation
*/
$toJson(options?: ToJsonOptions): object;
/**
* Convert model to database JSON format
* @returns Database-formatted object
*/
$toDatabaseJson(): object;
/**
* Set model properties from JSON
* @param json - JSON object to set
* @param options - Model options
* @returns This model instance
*/
$setJson(json: object, options?: ModelOptions): this;
/**
* Create model instance from JSON
* @param json - JSON object
* @param options - Model options
* @returns New model instance
*/
static fromJson(json: object, options?: ModelOptions): Model;Methods for getting and setting model IDs.
/**
* Get or set the model's ID
* @param id - Optional ID to set
* @returns Current ID or void if setting
*/
$id(id?: any): any;
/**
* Check if model has an ID
* @returns True if model has ID
*/
$hasId(): boolean;Static properties for configuring model behavior.
// Table name for the model
static get tableName(): string;
// Primary key column(s)
static get idColumn(): string | string[];
// JSON Schema for validation
static get jsonSchema(): object;
// Relationship mappings
static get relationMappings(): object;
// Columns that contain JSON data
static get jsonAttributes(): string[];
// Virtual attributes (not persisted)
static get virtualAttributes(): string[];
// Query modifiers
static get modifiers(): object;
// Column name mappers
static get columnNameMappers(): ColumnNameMappers;interface ModelOptions {
patch?: boolean;
skipValidation?: boolean;
old?: object;
}
interface ToJsonOptions {
virtuals?: boolean | string[];
shallow?: boolean;
}
interface CloneOptions {
shallow?: boolean;
}
interface FetchGraphOptions {
transaction?: Transaction;
skipFetched?: boolean;
}
interface TraverserFunction {
(model: Model, parentModel?: Model, relationName?: string): void;
}
interface QueryContext {
transaction?: Transaction;
[key: string]: any;
}
interface ColumnNameMappers {
parse(json: object): object;
format(json: object): object;
}Install with Tessl CLI
npx tessl i tessl/npm-objection