npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@storehouse/sequelize

v2.0.0

Published

Sequelize manager for @storehouse/core

Downloads

117

Readme

@storehouse/sequelize

Sequelize ORM manager adapter for @storehouse/core. Provides seamless integration with SQL databases using the Sequelize ORM.

Features

  • Type-safe database operations with full TypeScript support
  • Multi-database support (PostgreSQL, MySQL, SQLite, MariaDB, SQL Server, etc.)
  • Model registration and management with automatic initialization
  • Health check utilities for monitoring connection status
  • Multi-manager support via Storehouse registry
  • Full Sequelize API compatibility

Prerequisites

  • Database server (PostgreSQL, MySQL, SQLite, MariaDB, or SQL Server)
  • Node.js 18 or higher

Installation

npm install @storehouse/core sequelize @storehouse/sequelize

You'll also need to install the driver for your database:

# PostgreSQL
npm install pg pg-hstore

# MySQL / MariaDB
npm install mysql2

# SQLite
npm install sqlite3

# SQL Server
npm install tedious

Quick Start

1. Define Your Models

models/movie.ts

import { 
  DataTypes, 
  Model,
  ModelStatic,
  ModelAttributes, 
  ModelOptions, 
  Optional 
} from 'sequelize';
import { ModelSettings } from '@storehouse/sequelize';

interface MovieAttributes {
  id: number;
  title: string;
  rate?: number | null;
}

type MovieCreationAttributes = Optional<MovieAttributes, 'id'>;

interface MovieInstance
  extends Model<MovieAttributes, MovieCreationAttributes>, MovieAttributes { }

const movieSchema: ModelAttributes<MovieInstance, MovieAttributes> = {
  id: {
    type: DataTypes.INTEGER,
    autoIncrement: true,
    primaryKey: true
  },
  title: {
    type: DataTypes.STRING,
    allowNull: false,
    unique: true
  },
  rate: {
    type: DataTypes.TINYINT,
    validate: {
      max: 5,
      min: 1,
      isInt: true
    }
  }
};

const movieOptions: ModelOptions<Model<MovieAttributes, MovieCreationAttributes>> = {
  modelName: 'movies',
  tableName: 'movies'
};

export const movieSettings: ModelSettings<MovieAttributes, MovieCreationAttributes> = {
  attributes: movieSchema,
  options: movieOptions
};

2. Register the Manager

index.ts

import { Storehouse } from '@storehouse/core';
import { SequelizeManager } from '@storehouse/sequelize';
import { movieSettings } from './models/movie';

// Register the manager
Storehouse.add({
  local: {
    type: SequelizeManager, 
    config: {
      // Sequelize connection options
      options: {
        dialect: 'postgres',
        host: 'localhost',
        port: 5432,
        database: 'mydb',
        username: 'postgres',
        password: 'password',
        logging: false,
        pool: {
          max: 5,
          min: 0,
          acquire: 30000,
          idle: 10000
        }
      },
      // Model definitions
      models: [movieSettings]
    }
  }
});

3. Query the Database

import { Storehouse } from '@storehouse/core';
import { SequelizeManager } from '@storehouse/sequelize';
import { ModelStatic } from 'sequelize';
import { MovieInstance } from './models/movie';

// Get the manager
const manager = Storehouse.getManager<SequelizeManager>('local');

if (manager) {
  // Get the model
  const Movies = manager.getModel<ModelStatic<MovieInstance>>('movies');
  
  // Create a record
  const movie = await Movies.create({
    title: 'The Matrix',
    rate: 5
  });
  console.log('Created:', movie.toJSON());
  
  // Query records
  const allMovies = await Movies.findAll({
    where: { rate: 5 }
  });
  console.log('Found:', allMovies.length);
  
  // Use raw queries
  const [results] = await manager.query('SELECT * FROM movies WHERE rate > ?', {
    replacements: [3]
  });
  console.log('Results:', results);
}

API Reference

Configuration

The config object passed to the manager contains:

  • options? - Sequelize connection options:
    • dialect: Database type ('mysql', 'postgres', 'sqlite', 'mariadb', 'mssql')
    • host: Database host
    • port: Database port
    • database: Database name
    • username: Database user
    • password: Database password
    • logging: Logging function or false to disable
    • pool: Connection pool configuration
  • models? - Array of ModelSettings objects containing:
    • attributes: Model attribute definitions
    • options?: Model options (modelName, tableName, timestamps, etc.)
    • model?: Optional pre-defined model class extending Model

Helper Functions

The package provides helper functions that throw errors instead of returning undefined, making your code cleaner and safer.

getManager()

Retrieves a SequelizeManager instance from the registry.

import { Storehouse } from '@storehouse/core';
import { getManager } from '@storehouse/sequelize';

const manager = getManager(Storehouse, 'local');
await manager.sync();

Throws:

  • ManagerNotFoundError - If the manager doesn't exist
  • InvalidManagerConfigError - If the manager is not a SequelizeManager instance

getConnection()

Retrieves the Sequelize connection instance.

import { Storehouse } from '@storehouse/core';
import { getConnection } from '@storehouse/sequelize';
import { QueryTypes } from 'sequelize';

const sequelize = getConnection(Storehouse, 'local');
const users = await sequelize.query('SELECT * FROM users', {
  type: QueryTypes.SELECT
});

Throws:

  • ManagerNotFoundError - If the manager doesn't exist
  • InvalidManagerConfigError - If the connection is not a Sequelize instance

getModel()

Retrieves a model from the registry.

import { Storehouse } from '@storehouse/core';
import { getModel } from '@storehouse/sequelize';
import { ModelStatic } from 'sequelize';
import { MovieInstance } from './models/movie';

// Get model from default manager
const Movies = getModel<MovieInstance>(Storehouse, 'movies');
// or
// const Movies = getModel<ModelStatic<MovieInstance>>(Storehouse, 'movies');

// Get model from specific manager
const MoviesFromLocal = getModel<MovieInstance>(Storehouse, 'local', 'movies');
// or
// const MoviesFromLocal = getModel<ModelStatic<MovieInstance>>(Storehouse, 'local', 'movies');

Throws:

  • ModelNotFoundError - If the model doesn't exist

SequelizeManager Class

The SequelizeManager extends the Sequelize class with additional Storehouse integration features.

Methods

getConnection(): Sequelize

Returns the Sequelize instance (the manager itself).

const sequelize = manager.getConnection();
await sequelize.sync();
closeConnection(): Promise<void>

Closes the database connection and terminates all connections in the pool.

await manager.closeConnection();
getModel<M>(name): ModelStatic<M>

Retrieves a model that has been defined in this Sequelize instance.

const Movies = manager.getModel<MovieInstance>('movies');
const movie = await Movies.findByPk(1);
isConnected(): Promise<boolean>

Checks if the database connection is active by running an authentication test.

const connected = await manager.isConnected();
if (connected) {
  console.log('Database is connected');
}
healthCheck(): Promise<SequelizeHealthCheckResult>

Performs a comprehensive health check including connectivity test and metadata.

const health = await manager.healthCheck();

if (health.healthy) {
  console.log(`✓ Sequelize is healthy`);
  console.log(`  Database: ${health.details.dialect} v${health.details.databaseVersion}`);
  console.log(`  Latency: ${health.details.latency}`);
  console.log(`  Models: ${health.details.models?.join(', ')}`);
} else {
  console.error(`✗ Sequelize is unhealthy: ${health.message}`);
}

Health Check Result

The health check returns a detailed result object:

  • healthy: boolean - Overall health status
  • message: string - Descriptive message about the health status
  • timestamp: number - Timestamp when the health check was performed
  • latency: number - Response time in milliseconds
  • details: object - Detailed connection information
    • name: string - Manager name
    • dialect: string - Database dialect
    • databaseVersion?: string - Database version
    • models?: string[] - Array of registered model names
    • modelCount?: number - Total number of models
    • latency?: string - Response time in ms
    • error?: string - Error details (if unhealthy)

Advanced Usage

Extending Model Classes

For more advanced use cases, you can define model classes that extend Sequelize's Model:

import { 
  DataTypes, 
  Model, 
  ModelAttributes, 
  ModelOptions, 
  Optional  
} from 'sequelize';
import { ModelSettings } from '@storehouse/sequelize';

interface MovieAttributes {
  id: number;
  title: string;
  rate?: number | null;
}

type MovieCreationAttributes = Optional<MovieAttributes, 'id'>;

class Movie extends Model<MovieAttributes, MovieCreationAttributes> implements MovieAttributes {
  id!: number;
  title!: string;
  rate?: null | number;

  public readonly createdAt!: Date;
  public readonly updatedAt!: Date;

  // Custom static method
  static createMovie(title: string, rate?: number): Promise<Movie> {
    return Movie.create({ title, rate });
  }

  // Custom instance getter
  get fullTitle(): string {
    return `${this.id}: ${this.title}`;
  }
}

type MovieCtor = typeof Movie & { new(): Movie };

const movieSchema: ModelAttributes<Movie, MovieAttributes> = {
  id: {
    type: DataTypes.INTEGER,
    autoIncrement: true,
    primaryKey: true
  },
  title: {
    type: DataTypes.STRING,
    allowNull: false,
    unique: true
  },
  rate: {
    type: DataTypes.TINYINT,
    validate: {
      max: 5,
      min: 1,
      isInt: true
    }
  }
};

const movieOptions: ModelOptions<Model<MovieAttributes, MovieCreationAttributes>> = {
  modelName: 'movies',
  tableName: 'movies'
};

export const movieSettings: ModelSettings<MovieAttributes, MovieCreationAttributes> = {
  model: Movie,  // Provide the model class
  attributes: movieSchema,
  options: movieOptions
};

Usage:

import { getModel } from '@storehouse/sequelize';

const Movies = getModel<MovieCtor>(Storehouse, 'local', 'movies');
const movie = await Movies.createMovie('Blade', 5);
console.log(movie.fullTitle); // "1: Blade"

Multiple Managers

You can register multiple database connections:

import { Storehouse } from '@storehouse/core';
import { SequelizeManager } from '@storehouse/sequelize';

Storehouse.add({
  primary: {
    type: SequelizeManager,
    config: {
      options: {
        dialect: 'postgres',
        host: 'localhost',
        database: 'maindb',
        username: 'postgres',
        password: 'password'
      },
      models: [/* ... */]
    }
  },
  analytics: {
    type: SequelizeManager,
    config: {
      options: {
        dialect: 'mysql',
        host: 'analytics.example.com',
        database: 'analyticsdb',
        username: 'readonly',
        password: 'password'
      },
      models: [/* ... */]
    }
  }
});

// Access specific managers
const primaryManager = getManager(Storehouse, 'primary');
const analyticsManager = getManager(Storehouse, 'analytics');

Using the Manager Type

Set the manager type to simplify configuration and use string identifiers instead of class references:

import { Storehouse } from '@storehouse/core';
import { SequelizeManager } from '@storehouse/sequelize';

// Set default manager type
Storehouse.setManagerType(SequelizeManager);

// Now you can use type string instead of class
Storehouse.add({
  local: {
    type: '@storehouse/sequelize',
    config: {
      options: {
        dialect: 'mysql',
        host: 'localhost',
        database: 'mydb',
        username: 'root',
        password: 'password'
      },
      models: []
    }
  }
});

Transaction Management

import { Storehouse } from '@storehouse/core';
import { getConnection } from '@storehouse/sequelize';

const sequelize = getConnection(Storehouse, 'local');

// Managed transaction
await sequelize.transaction(async (t) => {
  await Movies.create({
    title: 'New Movie',
    rate: 4
  }, { transaction: t });
  
  await Reviews.create({
    movieId: 1,
    text: 'Great!'
  }, { transaction: t });
  
  // Automatically commits or rolls back
});

// Unmanaged transaction
const t = await sequelize.transaction();
try {
  await Movies.create({ title: 'New Movie', rate: 4 }, { transaction: t });
  await Reviews.create({ movieId: 1, text: 'Great!' }, { transaction: t });
  await t.commit();
} catch (error) {
  await t.rollback();
  throw error;
}

Logging

If you don't specify the logging option, you can enable the default logs using the @novice1/logger package:

import { Debug } from '@novice1/logger';

Debug.enable('@storehouse/sequelize*');

Or disable logging entirely:

Storehouse.add({
  local: {
    type: SequelizeManager,
    config: {
      options: {
        // ...
        logging: false
      }
    }
  }
});

TypeScript Support

The package is written in TypeScript and provides full type definitions for type-safe operations:

import { Storehouse } from '@storehouse/core';
import { ModelStatic } from 'sequelize';
import { SequelizeManager, getManager, getModel } from '@storehouse/sequelize';

// Typed manager
const manager = getManager<SequelizeManager>(Storehouse, 'local');

// Typed models
interface User {
  id: number;
  name: string;
  email: string;
}

const Users = getModel<User>(Storehouse, 'local', 'users');

// Type-safe query results
const users = await Users.findAll();
// users is typed as Model<User>[]

users.forEach(user => {
  console.log(user.name); // Fully typed
});

// Type-safe creation
const newUser = await Users.create({
  name: 'John Doe',
  email: '[email protected]'
});

Error Handling

All helper functions throw specific errors for better error handling:

import { Storehouse } from '@storehouse/core';
import { getManager, getModel } from '@storehouse/sequelize';
import {
  ManagerNotFoundError,
  InvalidManagerConfigError,
  ModelNotFoundError
} from '@storehouse/core';

try {
  const manager = getManager(Storehouse, 'nonexistent');
} catch (error) {
  if (error instanceof ManagerNotFoundError) {
    console.error('Manager not found:', error.message);
  } else if (error instanceof InvalidManagerConfigError) {
    console.error('Invalid manager type:', error.message);
  }
}

try {
  const Movies = getModel(Storehouse, 'nonexistent', 'movies');
} catch (error) {
  if (error instanceof ModelNotFoundError) {
    console.error('Model not found:', error.message);
  }
}

Best Practices

  1. Define models in separate files - Keep model definitions modular and reusable
  2. Use TypeScript interfaces - Define proper types for your model attributes
  3. Enable connection pooling - Configure appropriate pool sizes for production
  4. Use transactions - Wrap related operations in transactions for data consistency
  5. Handle errors properly - Implement reconnection logic for critical operations
  6. Use health checks - Monitor database health in production environments
  7. Close connections on shutdown - Call closeConnection() when shutting down
  8. Use parameterized queries - Always use replacements to prevent SQL injection
  9. Disable logging in production - Set logging: false or use conditional logging
  10. Leverage Sequelize features - Use validations, hooks, and associations

Resources

License

MIT