Tiny Memory DB
Tiny Memory DB is a zero-dependency, in-memory database library for JavaScript and TypeScript environments. Currently at version 0.4.2, it is in active development, with a release cadence that reflects its pre-1.0 status, meaning updates occur as features are implemented or bugs are addressed. Its primary differentiators are its minimal footprint and lack of external dependencies, making it ideal for lightweight data management. It provides a structured 'Table' abstraction for defining data schemas with attributes and primary keys, and supports a concise, string-based query language. Unlike persistent databases, Tiny Memory DB operates entirely in RAM, prioritizing speed and simplicity, though users can implement external mechanisms for data persistence if needed. It ships with comprehensive TypeScript types, ensuring type safety and an improved developer experience for TS projects.
Common errors
-
RangeError: JavaScript heap out of memory
cause The in-memory database is holding too much data, exceeding the JavaScript engine's heap limit.fixReduce the amount of data stored, or increase the Node.js memory limit if applicable (`--max-old-space-size`). Re-evaluate if an in-memory solution is appropriate for your dataset size. -
TypeError: Table is not a constructor
cause Attempting to import `Table` using CommonJS `require()` syntax or incorrect named import when the package is primarily ESM, or module resolution issues.fixEnsure you are using `import { Table } from 'tiny-memory-db';` with an environment configured for ESM (e.g., `"type": "module"` in package.json for Node.js, or a bundler like Webpack/Rollup). -
Property 'scan' does not exist on type 'Table<T>'. Did you mean 'query'?
cause Incorrect usage of `Table` instance methods, often trying to iterate directly on a query result object without calling a method to get iterable data.fixAfter calling `table.query()`, you typically need to call `.scan()` on the returned `ResultSet` to get the iterable data. Correct usage is `(await table.query(...)).scan()`.
Warnings
- breaking As a pre-1.0 library (currently v0.4.2), `tiny-memory-db` may introduce breaking API changes in minor or patch releases. It is recommended to pin exact versions and review release notes carefully during upgrades.
- gotcha Since `tiny-memory-db` is an in-memory database, all data resides in the application's RAM. Large datasets can lead to 'Out of Memory' errors, especially in environments with limited resources (e.g., serverless functions, browser tabs).
- gotcha The library does not provide built-in data persistence. Any data stored in a `Table` instance is lost when the application terminates or the instance is garbage collected. This is by design for an in-memory database.
- gotcha The string-based query language requires careful formatting. Complex queries or those relying on advanced operators might become cumbersome or less performant than dedicated query builders found in more feature-rich database solutions.
Install
-
npm install tiny-memory-db -
yarn add tiny-memory-db -
pnpm add tiny-memory-db
Imports
- Table
const { Table } = require('tiny-memory-db')import { Table } from 'tiny-memory-db' - Table<T>
import { Table } from 'tiny-memory-db'; const table = new Table({ attrs: 'id name' }); // Lacks type safetyimport { Table } from 'tiny-memory-db'; type MyData = { id: number; name: string }; const table = new Table<MyData>({ attrs: 'id name', funcs: ['id ->'] });
Quickstart
import { Table } from 'tiny-memory-db';
async function runExample() {
// Define the shape of our user data for type safety
type User = { id: number; name: string; email: string; createdAt: number };
// Create a new table for users, defining its attributes and a unique key
const usersTable = new Table<User>({
attrs: 'id name email createdAt',
funcs: ['id ->'] // 'id' is specified as a unique primary key
});
// Add some initial user data to the table
usersTable.put({ id: 1, name: 'Alice Wonderland', email: 'alice@example.com', createdAt: Date.now() - 100000 });
usersTable.put({ id: 2, name: 'Bob The Builder', email: 'bob@example.com', createdAt: Date.now() - 50000 });
usersTable.put({ id: 3, name: 'Charlie Chaplin', email: 'charlie@example.com', createdAt: Date.now() });
usersTable.put({ id: 4, name: 'David Jones', email: 'david@example.com', createdAt: Date.now() - 20000 });
console.log('--- All users initially stored ---');
// Retrieve and log all users in the table
for (const user of usersTable.scan()) {
console.log(user);
}
// Query for a specific user by their ID
console.log('
--- User with ID 2 ---');
const bobResults = await usersTable.query('id=2');
for (const user of bobResults.scan()) {
console.log(user);
}
// Query for users whose name contains 'Alice' using a regular expression
console.log('
--- Users with name containing "Alice" (using regex query) ---');
const usersContainingAlice = await usersTable.query('name~.*Alice.*');
for (const user of usersContainingAlice.scan()) {
console.log(user);
}
// Update an existing user's email address
const userToUpdate = (await usersTable.query('id=2')).scan()[0];
if (userToUpdate) {
usersTable.put({ ...userToUpdate, email: 'robert.builder@example.com' });
}
console.log('\n--- Updated Bob\'s email address ---');
const updatedBob = (await usersTable.query('id=2')).scan()[0];
console.log(updatedBob);
// Remove a user from the table based on their ID
usersTable.removeMatching('id=1');
console.log('\n--- Users after deleting Alice Wonderland (ID 1) ---');
for (const user of usersTable.scan()) {
console.log(user);
}
// Add another new user to demonstrate continued operation
usersTable.put({ id: 5, name: 'Eve Adams', email: 'eve@example.com', createdAt: Date.now() + 10000 });
console.log('\n--- All users after adding Eve ---');
for (const user of usersTable.scan()) {
console.log(user);
}
}
runExample();