CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-bookshelf

A lightweight ORM for PostgreSQL, MySQL, and SQLite3 with Promise-based interface and rich relationship support

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

Bookshelf

Bookshelf is a JavaScript ORM for Node.js built on the Knex SQL query builder. It provides both Promise-based and traditional callback interfaces, transaction support, eager/nested-eager relation loading, polymorphic associations, and support for one-to-one, one-to-many, and many-to-many relations.

Package Information

  • Package Name: bookshelf
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install bookshelf knex (plus database driver: pg, mysql, or sqlite3)

Core Imports

const knex = require('knex')(dbConfig);
const bookshelf = require('bookshelf')(knex);

Basic Usage

const knex = require('knex')({
  client: 'mysql',
  connection: {
    host: '127.0.0.1',
    user: 'your_db_user',
    password: 'your_password',
    database: 'myapp'
  }
});
const bookshelf = require('bookshelf')(knex);

// Define a model
const User = bookshelf.model('User', {
  tableName: 'users',
  posts() {
    return this.hasMany('Post');
  }
});

const Post = bookshelf.model('Post', {
  tableName: 'posts',
  user() {
    return this.belongsTo('User');
  }
});

// Use the models
const user = await new User({name: 'Alice'}).save();
const userWithPosts = await new User({id: 1}).fetch({withRelated: ['posts']});

Architecture

Bookshelf is built around several key components:

  • Bookshelf Instance: Created by passing a Knex instance, provides Model/Collection constructors and registry
  • Model Layer: Individual database rows with attribute management, relations, and lifecycle events
  • Collection Layer: Ordered sets of models with array-like methods and bulk operations
  • Relation System: Comprehensive relationship definitions including polymorphic associations
  • Event System: Lifecycle events for models and collections with Promise support
  • Query Builder Integration: Full access to underlying Knex query builder for complex queries

Capabilities

Bookshelf Instance

Core Bookshelf instance initialization and configuration, including model registry and plugin system.

/**
 * Creates a new Bookshelf instance
 * @param {Knex} knex - Initialized Knex client instance
 * @returns {Bookshelf} Bookshelf instance
 */
function Bookshelf(knex);

// Instance properties and methods
interface BookshelfInstance {
  VERSION: string;
  knex: Knex;
  Model: ModelConstructor;
  Collection: CollectionConstructor;
  
  model(name: string): Model;
  model(name: string, Model: ModelConstructor, staticProperties?: object): Model;
  collection(name: string): Collection;
  collection(name: string, Collection: CollectionConstructor, staticProperties?: object): Collection;
  resolve(name: string): any;
  transaction(callback: (transaction: Transaction) => Promise<any>): Promise<any>;
  plugin(plugin: string | Function | Array, options?: any): BookshelfInstance;
}

Bookshelf Instance

Model Operations

Complete CRUD operations, query building, and attribute management for individual database records.

// Static methods
interface ModelStatic {
  forge(attributes?: object, options?: object): Model;
  collection(models?: Model[], options?: object): Collection;
  count(column?: string, options?: object): Promise<number>;
  fetchAll(options?: object): Promise<Collection>;
  fetchPage(options?: object): Promise<{models: Collection, pagination: object}>;
  where(...args: any[]): Model;
  query(...args: any[]): Model;
}

// Instance methods
interface ModelInstance {
  fetch(options?: {withRelated?: string[], require?: boolean, transacting?: Transaction, columns?: string[], debug?: boolean}): Promise<Model>;
  save(key?: string | object, value?: any, options?: {method?: 'insert'|'update', patch?: boolean, transacting?: Transaction, debug?: boolean}): Promise<Model>;
  destroy(options?: {require?: boolean, transacting?: Transaction, debug?: boolean}): Promise<Model>;
  get(attribute: string): any;
  set(key: string | object, value?: any, options?: {unset?: boolean, silent?: boolean}): Model;
  has(attribute: string): boolean;
  unset(attribute: string, options?: object): Model;
  clear(options?: object): Model;
  isNew(): boolean;
  hasChanged(attribute?: string): boolean;
  previous(attribute?: string): any;
  previousAttributes(): object; 
  related(relationName: string): Model | Collection;
  clone(): Model;
  refresh(options?: {transacting?: Transaction}): Promise<Model>;
  toJSON(options?: {shallow?: boolean, omitPivot?: boolean}): object;
}

Models

Collection Operations

Array-like operations and bulk database operations for sets of models.

// Static methods
interface CollectionStatic {
  forge(models?: any[], options?: object): Collection;
}

// Instance methods  
interface CollectionInstance {
  fetch(options?: {withRelated?: string[], require?: boolean, transacting?: Transaction, debug?: boolean}): Promise<Collection>;
  fetchOne(options?: {require?: boolean, transacting?: Transaction}): Promise<Model>;
  fetchPage(options?: {page?: number, pageSize?: number, limit?: number, offset?: number, withRelated?: string[]}): Promise<{models: Collection, pagination: object}>;
  add(models: Model | Model[], options?: {at?: number, merge?: boolean, silent?: boolean}): Collection;
  remove(models: Model | Model[], options?: {silent?: boolean}): Collection;
  reset(models?: Model[], options?: {silent?: boolean}): Collection;
  create(attributes: object, options?: {wait?: boolean, transacting?: Transaction}): Promise<Model>;
  at(index: number): Model;
  get(id: any): Model;
  first(): Model;
  last(): Model;
  pluck(attribute: string): any[];
  where(attributes: object): Model[];
  clone(): Collection;
  length: number;
  models: Model[];
}

Collections

Relationships

Comprehensive relationship definitions including one-to-one, one-to-many, many-to-many, and polymorphic associations.

// Relation methods (available on Model instances)
interface RelationMethods {
  hasOne(Target: string | ModelConstructor, foreignKey?: string, foreignKeyTarget?: string): Relation;
  hasMany(Target: string | ModelConstructor, foreignKey?: string, foreignKeyTarget?: string): Relation;
  belongsTo(Target: string | ModelConstructor, foreignKey?: string, foreignKeyTarget?: string): Relation;
  belongsToMany(Target: string | ModelConstructor, tableName?: string, foreignKey?: string, otherKey?: string, foreignKeyTarget?: string, otherKeyTarget?: string): Relation;
  morphOne(Target: string | ModelConstructor, name: string, columnNames?: string[], morphValue?: any): Relation;
  morphMany(Target: string | ModelConstructor, name: string, columnNames?: string[], morphValue?: any): Relation;  
  morphTo(relationName: string, columnNames?: string[], ...targets: any[]): Relation;
  through(Interim: string | ModelConstructor, throughForeignKey?: string, otherKey?: string, throughForeignKeyTarget?: string, otherKeyTarget?: string): Relation;
}

Relationships

Events System

Lifecycle events for models and collections with both synchronous and asynchronous event handling.

// Event methods (available on Models and Collections)
interface EventMethods {
  on(events: string, callback: Function): this;
  off(events?: string, callback?: Function): this;
  trigger(event: string, ...args: any[]): this;
  triggerThen(event: string, ...args: any[]): Promise<any>;
  once(events: string, callback: Function): this;
}

// Model events: 'fetching', 'fetched', 'saving', 'creating', 'updating', 'saved', 'created', 'updated', 'destroying', 'destroyed'
// Collection events: 'fetched', 'add', 'remove', 'reset', 'sort', 'creating', 'attaching', 'attached', 'detaching', 'detached'

Events

Query Building

Direct access to Knex query builder for complex database operations and custom queries.

// Query building methods (available on Models and Collections)
interface QueryMethods {
  query(callback?: (qb: Knex.QueryBuilder) => void): this;
  where(...args: any[]): this;
  orderBy(column: string, direction?: string): this;
}

Query Building

Transactions

Database transaction support with automatic rollback on errors and connection management.

/**
 * Execute operations within a database transaction
 * @param {Function} callback - Transaction callback function receiving transaction object
 * @returns {Promise<any>} Promise resolving to callback result
 */
transaction(callback: (transaction: Transaction) => Promise<any>): Promise<any>;

Plugin System

Extend Bookshelf functionality with community and custom plugins.

/**
 * Load one or more plugins into this Bookshelf instance
 * @param {string|Function|Array} plugin - Plugin name, function, or array of plugins
 * @param {any} [options] - Plugin configuration options
 * @returns {BookshelfInstance} This Bookshelf instance for chaining
 */
plugin(plugin: string | Function | Array, options?: any): BookshelfInstance;

Error Types

Bookshelf provides specific error classes for common database operation failures.

// Available error classes (accessible via bookshelf instance)
interface ErrorTypes {
  NotFoundError: ErrorConstructor;        // Model/Collection not found with require: true
  EmptyError: ErrorConstructor;          // Collection is empty when required
  NoRowsUpdatedError: ErrorConstructor;  // Update operation affected no rows
  NoRowsDeletedError: ErrorConstructor;  // Delete operation affected no rows  
  ModelNotResolvedError: ErrorConstructor; // Model name cannot be resolved from registry
}

// Access errors from bookshelf instance
const {
  NotFoundError,
  EmptyError, 
  NoRowsUpdatedError,
  NoRowsDeletedError,
  ModelNotResolvedError
} = bookshelf;

// Also available on Model and Collection constructors
const { NotFoundError: ModelNotFound } = bookshelf.Model;
const { EmptyError: CollectionEmpty } = bookshelf.Collection;

Usage Examples:

try {
  // This will throw NotFoundError if no user found
  const user = await new User({id: 999}).fetch({require: true});
} catch (error) {
  if (error instanceof bookshelf.NotFoundError) {
    console.log('User not found');
  }
}

try {
  // This will throw EmptyError if no users found  
  const users = await Users.forge().fetch({require: true});
} catch (error) {
  if (error instanceof bookshelf.EmptyError) {
    console.log('No users in collection');
  }
}

Types

// Core type definitions
interface Transaction {
  // Knex transaction object
  commit(): Promise<void>;
  rollback(): Promise<void>;
}

interface Relation {
  where(...args: any[]): Relation;
  query(callback: (qb: Knex.QueryBuilder) => void): Relation;
  through(Interim: string | ModelConstructor, throughForeignKey?: string, otherKey?: string): Relation;
  withPivot(...columns: string[]): Relation;
}

interface ModelConstructor {
  new(attributes?: object, options?: object): Model;
  forge(attributes?: object, options?: object): Model;
  extend(protoProps?: object, staticProps?: object): ModelConstructor;
}

interface CollectionConstructor {
  new(models?: Model[], options?: object): Collection;
  forge(models?: Model[], options?: object): Collection;
  extend(protoProps?: object, staticProps?: object): CollectionConstructor;
}

docs

bookshelf-instance.md

collections.md

events.md

index.md

models.md

query-building.md

relationships.md

tile.json