Skip to content

ThisPeople/db

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ThisPeopleDB

In-memory database from scratch on Node.js with a custom query engine, JSON persistence, and an interactive REPL.

Features

  • 🗄️ In-memory storage — lightning fast, zero dependencies
  • 🔍 Custom query engineWHERE, ORDER BY, LIMIT, OFFSET, field selection
  • 🧩 Rich operators$eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $like, $regex, $exists, $and, $or
  • 💾 JSON persistence — auto-saves every 30s (configurable) + saves on exit
  • 📋 Schema validation — define types, required fields, defaults
  • 🎮 Interactive REPL — SQL-like syntax for ad-hoc queries
  • 🔗 Fluent QueryBuilder API — chain .where(), .order(), .limit(), .offset(), .fields()
  • 📊 Indexes — create indexes on fields for faster lookups
  • 🪶 Zero dependencies — pure Node.js

Quick Start

# Start the REPL
node src/repl.js

# Run the demo
node src/index.js

# Run advanced example
node examples/advanced.js

Programmatic API

import Database from './src/database.js';

const db = new Database('mydb');
await db.init();

// Create table with schema
const users = db.createTable('users', {
  name:   { type: 'string', required: true },
  age:    { type: 'number', default: 0 },
  email:  { type: 'string' },
  role:   { type: 'string', default: 'user' },
  active: { type: 'boolean', default: true },
});

// Insert
users.insert({ name: 'Alice', age: 30, email: 'alice@test.com' });

// Query
users.find({ where: { age: { $gt: 25 } }, order: { name: 'asc' }, limit: 10 });

// Fluent API
db.query('users')
  .where({ active: true })
  .order({ name: 'asc' })
  .limit(5)
  .find();

// Update
users.update({ where: { name: 'Alice' } }, { age: 31 });

// Delete
users.delete({ where: { active: false } });

// Count
users.count({ role: 'admin' });

// Save & close
await db.close();

REPL Commands

Meta commands

Command Description
.tables List all tables
.schema <table> Show table schema
.save Force save to disk
.load <path> Load from JSON file
.help Show help
.exit / .quit Exit
.clear Clear screen

SQL-like queries

CREATE TABLE users (name string REQUIRED, age number DEFAULT 0, email string)
DROP TABLE users
INSERT INTO users (name, age) VALUES ('Alice', 30)
SELECT * FROM users WHERE age > 25 ORDER BY name ASC LIMIT 10
SELECT name, email FROM users WHERE role = 'admin'
UPDATE users SET age = 31 WHERE name = 'Alice'
DELETE FROM users WHERE age < 18
COUNT FROM users

WHERE operators

=, !=, <>, >, >=, <, <=, LIKE, IN (...), NOT IN (...)

Combine with AND / OR.

Persistence

Data is stored in ./data/<db-name>.json. Auto-save runs every 30 seconds (configurable via saveInterval option). Data is also saved on graceful shutdown.

API Reference

src/database.js — Core Engine

Utility Functions

Function Description
generateId() Generates a unique ID using timestamp + random suffix
cloneDeep(value) Deep-clones a value via JSON.parse(JSON.stringify(...))
validateSchema(schema) Validates a schema definition structure
validateRecord(schema, record) Validates a record against its schema (types, required, defaults)
parseWhere(condition) Normalizes a WHERE condition object
evaluateCondition(cond, record) Evaluates a condition against a single record
parseOrder(orderSpec) Normalizes an ORDER specification
applyOrder(records, orderSpec) Sorts records by the given order specification

Query Operators

Operator Description
$eq Equal to
$ne Not equal to
$gt Greater than
$gte Greater than or equal
$lt Less than
$lte Less than or equal
$in Value in array
$nin Value not in array
$like SQL-style pattern match (% wildcard)
$regex Regular expression match
$exists Field exists check
$and Logical AND (array of conditions)
$or Logical OR (array of conditions)

class Table

Represents a single database table with schema enforcement and indexing.

Method Description
constructor(name, schema, options) Creates a new table. Options: { autoId: true }
insert(data) Inserts a record, returns the record with generated id
insertMany(dataArray) Bulk inserts multiple records
get(id) Retrieves a record by its id
find(query) Queries records with { where, order, limit, offset, fields }
findOne(query) Returns the first matching record
update(query, changes) Updates matching records, returns { modified } count
delete(query) Deletes matching records, returns { deleted } count
count(where) Counts records matching a condition
createIndex(field) Creates an index on the specified field
toJSON() Serializes the table for persistence
fromJSON(json) Deserializes a table from JSON (static)

class Database

Manages multiple tables with persistence and auto-save.

Method Description
constructor(name, options) Creates a database instance. Options: { saveDir, saveInterval }
createTable(name, schema, options) Creates and returns a new table
dropTable(name) Drops a table by name
table(name) Returns a table by name (throws if not found)
hasTable(name) Checks if a table exists
listTables() Returns an array of table names
save() Persists all tables to disk (atomic write)
load() Loads all tables from disk
close() Saves and stops auto-save, cleans up
init() Initializes: loads from disk, starts auto-save
query(tableName) Returns a QueryBuilder for the given table

class QueryBuilder

Fluent API for building and executing queries.

Method Description
where(condition) Sets the WHERE condition
order(orderSpec) Sets the ORDER specification
limit(n) Sets the maximum number of results
offset(n) Sets the number of records to skip
fields(fieldList) Sets the fields to return
find() Executes the query and returns results
findOne() Executes and returns the first match
count() Executes a count query

src/repl.js — Interactive REPL

SQL Parser

Function Description
tokenize(input) Tokenizes a SQL-like input string into tokens
parseValue(token) Parses a token into a typed JS value
parseFieldList(tokens, startIdx) Parses (field1, field2, ...)
parseValueList(tokens, startIdx) Parses (val1, val2, ...) with type coercion
parseWhereClause(tokens, startIdx) Parses WHERE field op value [AND/OR ...]
parseOrderBy(tokens, startIdx) Parses ORDER BY field [ASC|DESC] [, ...]
parseLimitOffset(tokens, startIdx) Parses LIMIT n [OFFSET n]

Command Executor & Display

Function Description
executeSQL(db, input) Executes a SQL-like command against the database
formatTable(data, maxColWidth) Formats records as an ASCII table
countAnsi(str) Counts ANSI escape code characters
printResult(result) Displays a command result to the console
showHelp() Prints the interactive help screen
main() REPL entry point — starts the readline interface

Supported SQL Commands

Command Syntax
CREATE TABLE CREATE TABLE name (field TYPE [REQUIRED] [DEFAULT val], ...)
DROP TABLE DROP TABLE name
INSERT INTO INSERT INTO name [(field, ...)] VALUES (val, ...)
SELECT SELECT [field, ...] FROM name [WHERE ...] [ORDER BY ...] [LIMIT n] [OFFSET n]
UPDATE UPDATE name SET field=val, ... [WHERE ...]
DELETE DELETE FROM name [WHERE ...]
COUNT COUNT FROM name [WHERE ...]

Meta-Commands

Command Description
.tables List all tables with record counts
.schema <name> Show table schema as JSON
.save Force-save database to disk
.load <path> Load database from a JSON file
.help Display help text
.exit / .quit Exit the REPL (auto-saves)
.clear Clear the terminal screen

src/index.js — Demo

Function Description
main() Demonstrates all API features: table creation, CRUD, queries, indexes, persistence

Project Structure

src/
  database.js    — Core engine: Database, Table, QueryBuilder, query parser (1063 lines)
  repl.js        — Interactive REPL with SQL-like syntax (950 lines)
  index.js       — Main entry point with demo (151 lines)
examples/
  advanced.js    — Advanced queries, indexes, bulk operations
data/            — JSON persistence files (auto-created)

About

A This People DataBase repository

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages