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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@rinari/orm

v1.0.0

Published

Standalone, dependency-less ORM for RINARI framework with pluggable drivers

Readme

@rinari/orm

Lightweight, modular ORM for Node.js and Bun with pluggable database drivers.

npm version License

Overview

@rinari/orm is the core package of the Rinari ORM framework, providing a powerful yet simple API for database operations. It features a pluggable driver architecture, full TypeScript support, and works seamlessly with both synchronous and asynchronous drivers.

Features

  • Zero Dependencies - Core ORM has no external dependencies
  • Pluggable Drivers - Support for multiple database backends
  • Multi-Database - Manage multiple databases simultaneously
  • Type-Safe - Full TypeScript support with automatic type inference
  • Sync and Async - Compatible with both sync and async drivers
  • Lightweight - Minimal overhead, maximum performance
  • Transaction Support - ACID transactions for data integrity
  • Query Operators - Rich query language with comparison, pattern matching, and range operators

Installation

npm install @rinari/orm

Choose a driver:

# SQLite (recommended for most applications)
npm install @rinari/sqlite

Quick Start

import { ORM } from '@rinari/orm';
import { SQLiteDriver } from '@rinari/sqlite';
import { DataTypes } from '@rinari/types';

// Initialize ORM with driver
const orm = new ORM({
  driver: new SQLiteDriver({ storageDir: './data' }),
});

// Define a model
const User = orm.define('mydb', 'users', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  username: { type: DataTypes.TEXT, notNull: true },
  email: { type: DataTypes.TEXT, unique: true },
});

// Create a record
const user = User.create({
  username: 'alice',
  email: '[email protected]',
});

console.log(user);
// { id: 1, username: 'alice', email: '[email protected]' }

// Query records
const users = User.findAll({
  where: { username: { $like: 'a%' } },
  orderBy: [['username', 'ASC']],
});

API Reference

ORM Class

Constructor

const orm = new ORM({
  driver: driverInstance,  // Required: Database driver instance
  config?: driverConfig    // Optional: Driver-specific configuration
});

Core Methods

define(dbName, tableName, schema)

Define a model and create its table in the database.

Parameters:

  • dbName (string) - Database name
  • tableName (string) - Table name
  • schema (object) - Column definitions

Returns: Model instance

const User = orm.define('mydb', 'users', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  username: { type: DataTypes.TEXT, notNull: true },
  email: { type: DataTypes.TEXT, unique: true },
  age: { type: DataTypes.INTEGER },
  status: { type: DataTypes.TEXT, default: 'active' },
  createdAt: { type: DataTypes.DATETIME },
});

Column Options:

| Option | Type | Description | |--------|------|-------------| | type | DataType | Required. Data type from DataTypes enum | | primaryKey | boolean | Mark column as primary key | | autoIncrement | boolean | Auto-increment (INTEGER primary keys only) | | notNull | boolean | NOT NULL constraint | | unique | boolean | UNIQUE constraint | | default | any | Default value for the column | | references | object | Foreign key relationship |

model(dbName, tableName)

Retrieve an existing model.

const User = orm.model('mydb', 'users');
table(tableName, dbName?)

Get a model by table name. Defaults to 'default' database if dbName is omitted.

const User = orm.table('users');
const User = orm.table('users', 'mydb');
hasModel(dbName, tableName)

Check if a model exists.

if (orm.hasModel('mydb', 'users')) {
  console.log('User model exists');
}
getDatabases()

Get list of all database names.

const databases = orm.getDatabases();
console.log(databases); // ['mydb', 'analytics', 'content']
disconnect()

Disconnect the driver and close all connections.

orm.disconnect();
driverInfo

Get driver metadata.

console.log(orm.driverInfo);
// { name: 'sqlite', version: '1.0.0' }

Model Class

Models provide CRUD operations and queries for database tables.

Query Methods

findOne(options)

Find a single record.

Parameters:

  • options.where - Filter conditions
  • options.select - Columns to select

Returns: Record object or null

const user = User.findOne({
  where: { email: '[email protected]' },
});
findAll(options)

Find multiple records.

Parameters:

  • options.where - Filter conditions
  • options.orderBy - Sort order
  • options.limit - Maximum records to return
  • options.offset - Number of records to skip
  • options.select - Columns to select

Returns: Array of records

const users = User.findAll({
  where: { status: 'active' },
  orderBy: [['createdAt', 'DESC']],
  limit: 10,
  offset: 0,
});
findById(id)

Find record by primary key.

const user = User.findById(1);
count(where?)

Count records matching criteria.

const total = User.count();
const active = User.count({ status: 'active' });

Create/Update Methods

create(data)

Create a new record.

const user = User.create({
  username: 'bob',
  email: '[email protected]',
  age: 30,
});
bulkCreate(records)

Create multiple records.

const users = User.bulkCreate([
  { username: 'user1', email: '[email protected]' },
  { username: 'user2', email: '[email protected]' },
  { username: 'user3', email: '[email protected]' },
]);
update(data, where)

Update records matching criteria.

Returns: Number of updated records

const count = User.update(
  { status: 'verified' },
  { id: 1 }
);
console.log(`Updated ${count} record(s)`);
bulkUpdate(updates)

Update multiple records with different conditions.

const count = User.bulkUpdate([
  { where: { id: 1 }, data: { status: 'active' } },
  { where: { id: 2 }, data: { status: 'inactive' } },
]);
delete(where)

Delete records matching criteria.

Returns: Number of deleted records

const count = User.delete({ status: 'deleted' });
console.log(`Deleted ${count} record(s)`);
bulkDelete(whereConditions)

Delete multiple records with different conditions.

const count = User.bulkDelete([
  { status: 'deleted' },
  { lastLogin: { $lt: '2020-01-01' } },
]);

Aggregation Methods

sum(field, where?)

Sum numeric field values.

const totalAge = User.sum('age');
const activeUserAge = User.sum('age', { status: 'active' });
avg(field, where?)

Calculate average of field values.

const avgAge = User.avg('age');
min(field, where?)

Find minimum value.

const minAge = User.min('age');
max(field, where?)

Find maximum value.

const maxAge = User.max('age');

Index Methods

createIndex(indexName, options)

Create a database index.

User.createIndex('idx_email', {
  columns: ['email'],
  unique: true,
});

User.createIndex('idx_status_created', {
  columns: ['status', 'createdAt'],
});
dropIndex(indexName)

Drop an existing index.

User.dropIndex('idx_email');

Transaction Methods

transaction(fn)

Execute operations in a transaction. All operations succeed or all fail.

User.transaction(() => {
  User.create({ username: 'alice', email: '[email protected]' });
  User.create({ username: 'bob', email: '[email protected]' });
  User.update({ verified: true }, { username: 'alice' });
  
  // If any operation fails, all changes are rolled back
});

Advanced Usage

Query Operators

Build complex queries with operators:

// Comparison operators
User.findAll({ where: { age: { $gt: 18 } } });                // age > 18
User.findAll({ where: { age: { $gte: 18 } } });               // age >= 18
User.findAll({ where: { age: { $lt: 65 } } });                // age < 65
User.findAll({ where: { age: { $lte: 65 } } });               // age <= 65
User.findAll({ where: { status: { $ne: 'deleted' } } });      // status != 'deleted'

// Set operators
User.findAll({
  where: { status: { $in: ['active', 'pending'] } }
});

User.findAll({
  where: { status: { $notIn: ['deleted', 'banned'] } }
});

// Pattern matching
User.findAll({
  where: { email: { $like: '%@gmail.com' } }
});

// Range queries
User.findAll({
  where: { age: { $between: [18, 65] } }
});

// Complex conditions
User.findAll({
  where: {
    age: { $gte: 18, $lt: 65 },
    status: { $in: ['active', 'verified'] },
    email: { $like: '%@company.com' },
  },
});

Available operators:

| Operator | Description | Example | |----------|-------------|---------| | $gt | Greater than | { age: { $gt: 18 } } | | $gte | Greater than or equal | { age: { $gte: 18 } } | | $lt | Less than | { age: { $lt: 65 } } | | $lte | Less than or equal | { age: { $lte: 65 } } | | $ne | Not equal | { status: { $ne: 'deleted' } } | | $in | In array | { status: { $in: ['active', 'pending'] } } | | $notIn | Not in array | { status: { $notIn: ['deleted'] } } | | $like | Pattern match | { email: { $like: '%@gmail.com' } } | | $between | Between range | { age: { $between: [18, 65] } } |

TypeScript Support

Full TypeScript support with automatic type inference:

import { ORM } from '@rinari/orm';
import { SQLiteDriver } from '@rinari/sqlite';
import { DataTypes } from '@rinari/types';

const orm = new ORM({
  driver: new SQLiteDriver({ storageDir: './data' }),
});

const User = orm.define('mydb', 'users', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  username: { type: DataTypes.TEXT, notNull: true },
  email: { type: DataTypes.TEXT, unique: true },
  age: { type: DataTypes.INTEGER },
});

// TypeScript automatically infers types
const user = User.findOne({ where: { id: 1 } });
// user: { id: number; username: string; email: string; age: number } | null

const users = User.findAll();
// users: Array<{ id: number; username: string; email: string; age: number }>

Multiple Databases

Manage multiple databases simultaneously:

import { ORM } from '@rinari/orm';
import { SQLiteDriver } from '@rinari/sqlite';
import { DataTypes } from '@rinari/types';

const orm = new ORM({
  driver: new SQLiteDriver({ storageDir: './data' }),
});

// Users database
const User = orm.define('users_db', 'users', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  username: { type: DataTypes.TEXT, notNull: true },
});

// Content database
const Post = orm.define('content_db', 'posts', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  title: { type: DataTypes.TEXT, notNull: true },
  content: { type: DataTypes.TEXT },
});

// Analytics database
const Event = orm.define('analytics_db', 'events', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  name: { type: DataTypes.TEXT, notNull: true },
  timestamp: { type: DataTypes.DATETIME },
});

// Creates separate database files:
// ./data/users_db.sqlite
// ./data/content_db.sqlite
// ./data/analytics_db.sqlite

Examples

Complete CRUD Example

import { ORM } from '@rinari/orm';
import { SQLiteDriver } from '@rinari/sqlite';
import { DataTypes } from '@rinari/types';

const orm = new ORM({
  driver: new SQLiteDriver({ storageDir: './data' }),
});

const User = orm.define('mydb', 'users', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  username: { type: DataTypes.TEXT, notNull: true },
  email: { type: DataTypes.TEXT, unique: true },
  status: { type: DataTypes.TEXT, default: 'active' },
});

// Create
const alice = User.create({
  username: 'alice',
  email: '[email protected]',
});

// Read
const user = User.findOne({ where: { username: 'alice' } });
const allUsers = User.findAll({ where: { status: 'active' } });

// Update
User.update({ status: 'verified' }, { id: alice.id });

// Delete
User.delete({ status: 'inactive' });

// Count
const total = User.count();

Working with Transactions

User.transaction(() => {
  const alice = User.create({
    username: 'alice',
    email: '[email protected]',
  });
  
  const bob = User.create({
    username: 'bob',
    email: '[email protected]',
  });
  
  User.update({ verified: true }, { id: alice.id });
  
  // All operations succeed together or fail together
});

Driver Examples

SQLite Driver

import { ORM } from '@rinari/orm';
import { SQLiteDriver } from '@rinari/sqlite';

const orm = new ORM({
  driver: new SQLiteDriver({
    storageDir: './databases',
    verbose: false,      // SQL query logging
    readonly: false,     // Read-only mode
  }),
});

Best Practices

  1. Use transactions for multiple related operations
  2. Create indexes on frequently queried columns
  3. Select specific columns when you don't need all data
  4. Use bulk operations instead of loops for better performance
  5. Close connections properly with orm.disconnect()
  6. Handle errors appropriately in production code

Related Packages

Documentation

Support

License

OpenUwU Open License (OUOL-1.0) - See LICENSE for details.