dtable-js
A lightweight and flexible package for managing tabular data with features similar to .NET's DataTable. This package provides an efficient way to handle structured data with support for typed columns, data validation, sorting, and filtering. It can be used with any SQL database like PostgreSQL, MySQL, SQLite, or SQL Server.
Installation
npm install dtable-js
Basic Usage
const { DataTable } = require('dtable-js');
const DataTable = require('dtable-js').DataTable;
const dt = new DataTable('Users');
Database Integration
The library seamlessly integrates with any database query results. You can directly load data from:
- PostgreSQL
- MySQL
- SQLite
- SQL Server
- Any other database that returns query results as objects
Example with different databases:
const { Pool } = require('pg');
const pool = new Pool(config);
const dt = new DataTable('Products');
const result = await pool.query('SELECT * FROM products');
dt.loadFromQuery(result.rows);
const mysql = require('mysql2/promise');
const connection = await mysql.createConnection(config);
const [rows] = await connection.execute('SELECT * FROM products');
dt.loadFromQuery(rows);
const sqlite3 = require('sqlite3');
const db = new sqlite3.Database('mydb.sqlite');
db.all('SELECT * FROM products', [], (err, rows) => {
dt.loadFromQuery(rows);
});
Features
- Strongly typed columns
- Row management
- Sorting and filtering
- Data validation
- Query result loading
- Database integration
- DataSet support for related tables
- DataView for filtered views of tables
API Reference
Table Operations
Creating a Table
const dt = new DataTable('TableName');
Adding Columns
dt.addColumn('age', 'number');
dt.addColumn('name', 'string');
dt.addColumn('birthDate', 'date');
dt.addColumn('description');
Adding Rows
dt.addRow({ name: 'John', age: 30, birthDate: new Date('1993-01-01') });
dt.addRow(['Jane', 25, new Date('1998-01-01')]);
const row = dt.newRow();
row.set('name', 'Alice');
row.set('age', 28);
dt.rows.add(row);
Row Operations
const value = dt.rows(0).get("value");
const name = dt.rows(1).get("name");
const name = row.get('name');
const age = row.item('age');
row.set('name', 'NewName');
dt.removeRow(0);
dt.clear();
Data Operations
Filtering Data
The DataTable provides two methods for filtering data:
select(): Works directly with row values as plain objects. Access values using dot notation (e.g., row.age)
findRows(): Works with DataRow objects. Access values using the get() method (e.g., row.get('age'))
Examples:
const adults = dt.select(row => row.age >= 18);
const activeUsers = dt.select(row => row.age > 25 && row.active === true);
const johns = dt.findRows({ name: 'John' });
const over25 = dt.findRows(row => row.get('age') > 25);
Advanced Filtering Criteria
DataTable-js supports various operators for advanced filtering. Here are all available operators:
dt.findRows({
age: { $gt: 25 },
score: { $gte: 90 },
price: { $lt: 100 },
quantity: { $lte: 50 },
status: { $ne: 'active' },
category: { $in: ['A', 'B', 'C'] },
name: { $contains: 'john' },
email: /gmail\.com$/,
active: true,
type: 'user'
});
const results = dt.findRows({
age: { $gt: 18, $lt: 30 },
name: { $contains: 'smith' },
roles: { $in: ['admin', 'editor'] },
email: /^[a-z]+@company\.com$/
});
const filtered = dt.findRows(row => {
const age = row.get('age');
const status = row.get('status');
return age > 25 && status === 'active';
});
All supported operators:
$gt: Greater than
$gte: Greater than or equal to
$lt: Less than
$lte: Less than or equal to
$ne: Not equal to
$in: Value exists in array
$contains: String contains value
- RegExp: Support for regular expressions
Sorting
dt.sort('age', 'asc');
dt.sortMultiple(
{ column: 'age', order: 'desc' },
{ column: 'name', order: 'asc' }
);
dt.sortBy(row => row.get('age') + row.get('name'));
Loading Data from Database
const { Pool } = require('pg');
const pool = new Pool(config);
const dt = new DataTable('Products');
const result = await pool.query('SELECT * FROM products WHERE category = $1', ['electronics']);
dt.loadFromQuery(result.rows);
const mysql = require('mysql2/promise');
const connection = await mysql.createConnection(config);
const [rows] = await connection.execute('SELECT * FROM products WHERE price > ?', [100]);
dt.loadFromQuery(rows);
await dt.loadFromQueryAsync(
pool.query('SELECT * FROM products').then(result => result.rows)
);
const data = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' }
];
dt.loadFromQuery(data);
Column Operations
dt.columnExists('name');
dt.removeColumn('age');
Table Manipulation
const newTable = dt.clone();
for (const row of newTable) {
console.log(row.get('name'));
}
DataSet Operations
DataSet allows you to manage multiple related tables and define relationships between them.
const { DataSet, DataTable } = require('dtable-js');
const ds = new DataSet('CompanyData');
const employees = ds.addTable('Employees');
employees.addColumn('id', 'number');
employees.addColumn('name', 'string');
employees.addColumn('departmentId', 'number');
const departments = ds.addTable('Departments');
departments.addColumn('id', 'number');
departments.addColumn('name', 'string');
departments.addRow({ id: 1, name: 'HR' });
departments.addRow({ id: 2, name: 'IT' });
employees.addRow({ id: 1, name: 'John', departmentId: 2 });
employees.addRow({ id: 2, name: 'Jane', departmentId: 1 });
const relation = ds.addRelation(
'EmpDeptRelation',
'Departments',
'Employees',
'id',
'departmentId'
);
const itDept = departments.findOne({ id: 2 });
const itEmployees = ds.getChildRows(itDept, 'EmpDeptRelation');
console.log(itEmployees);
const john = employees.findOne({ name: 'John' });
const johnsDept = ds.getParentRow(john, 'EmpDeptRelation');
console.log(johnsDept.get('name'));
DataView Operations
DataView provides a filtered and sorted view of a DataTable.
const { DataTable, DataView } = require('dtable-js');
const users = new DataTable('Users');
users.addColumn('id', 'number');
users.addColumn('name', 'string');
users.addColumn('age', 'number');
users.addColumn('active', 'boolean');
users.addRow({ id: 1, name: 'John', age: 25, active: true });
users.addRow({ id: 2, name: 'Jane', age: 30, active: true });
users.addRow({ id: 3, name: 'Bob', age: 22, active: false });
users.addRow({ id: 4, name: 'Alice', age: 35, active: true });
const activeUsersView = new DataView(
users,
{ active: true },
'age',
'desc'
);
console.log(`Active users: ${activeUsersView.count}`);
const oldest = activeUsersView.firstRow;
console.log(oldest.get('name'));
for (const row of activeUsersView) {
console.log(`${row.get('name')}: ${row.get('age')}`);
}
const activeUsersTable = activeUsersView.toTable();
const activeUsersArray = activeUsersView.toArray();
Supported Data Types
- string
- number
- date
- boolean
Advanced Database Usage
The DataTable automatically creates columns based on the database query results, matching the types from your database:
- INTEGER/BIGINT → number
- VARCHAR/TEXT → string
- TIMESTAMP/DATE → date
- BOOLEAN → boolean
This makes it perfect for scenarios where you need to:
- Cache database results
- Manipulate query results before display
- Create temporary data structures from database queries
- Transform data before sending to the frontend
Error Handling
The library throws errors for:
- Invalid column operations
- Type mismatches
- Null violations
- Duplicate columns
License
MIT