A file-based & memory-efficient, serverless, ACID compliant, relational database management system 🔥
- Lightweight 🪶
- Minimalist ⚪ (but powerful)
- 100% TypeScript 🔷
- Super-Fast ⚡ (built-in caching system)
- ATOMIC 🔒 File lock for writing
- Built-in form-validation included 😎
- Suitable for large data 📃 (tested with 4M records)
- Support Compression ✳️ (using built-in nodejs zlib)
- Support Table Joins 🔗
- Low memory-usage 📉 (3-5mb)
- Safe 🔒 (no sql or javascript injections)
- Easy to use 🍞
- ... and much more 🚀
import Inibase from "inibase";
const db = new Inibase("databaseName");
// Get all items from "user" table
const users = await db.get("user");
// Read page 2 content
const users = await db.get("user", undefined, { page: 2, per_page: 15 });
// Get only required columns to improve speed
const users = await db.get("user", undefined, {
columns: ["username", "address.street", "hobbies.name"],
});
// Get items from "user" table where "favoriteFoods" does not includes "Pizza" or "Burger"
const users = await db.get("user", { favoriteFoods: "![]Pizza,Burger" });
[!NOTE] Enjoy using Inibase? Consider sponsoring us via PayPal
Your support helps us maintain and improve our services.
Thank you! 🫰
<npm|pnpm|yarn> install inibase
Inibase
organizes data into databases, tables, and columns, each stored in separate files.
- POST: New data is appended to column files efficiently.
- GET: Data retrieval is optimized by reading files line-by-line.
- PUT: Updates are streamlined, with only the relevant file being modified.
- DELETE: Removes lines from column files for swift deletion.
This structure ensures efficient storage, retrieval, and updates, making our system scalable and high-performing for diverse datasets and applications.
npx inibase -p <databaseFolderPath>
GET
get <tableName> -w <ID|LineNumber|Criteria> -p <pageNumber> -l <perPage> -c <columnName1> -c <columnName2>POST
post <tableName> -d <InisonStrigifedData>PUT
put <tableName> -d <InisonStrigifedData> -w <ID|LineNumber|Criteria>DELETE
delete <tableName> -w <ID|LineNumber|Criteria>
Tables
Config
interface { compression: boolean; cache: boolean; prepend: boolean; }Schema
interface { id: number; // stored as a Number but displayed as a hashed ID key: string; required?: boolean; unique?: boolean; type: "string" | "number" | "boolean" | "date" | "email" | "url" | "password" | "html" | "ip" | "json" | "id"; } interface Table { id: number; key: string; required?: boolean; type: "table"; table: string; } interface Array { id: number; key: string; required?: boolean; type: "array"; children: string|string[]; } interface ObjectOrArrayOfObjects { id: number; key: string; required?: boolean; type: "object" | "array"; children: Schema; }Create Table
import Inibase from "inibase"; const db = new Inibase("/databaseName"); const userTableConfig = { compression: true, cache: true, prepend: false } const userTableSchema = [ { key: "username", type: "string", required: true, }, { key: "email", type: "string", required: true, }, { key: "age", type: "number", required: true, }, { key: "isActive", type: "boolean", // required: false }, { key: "hobbies", type: "array", children: [ { key: "name", type: "string", // required: false }, { key: "level", type: "string", // required: false }, ], }, { key: "favoriteFoods", type: "array", children: "string", // required: false }, { key: "address", type: "object", children: [ { key: "street", type: "string", // required: false }, { key: "city", type: "string", // required: false }, { key: "country", type: "string", // required: false }, ], }, ]; await db.createTable("user", userTableSchema, userTableConfig);Update Table
Add field
import Inibase from "inibase"; const db = new Inibase("/databaseName"); const userTableSchema = (await db.getTable("user")).schema; const newUserTableSchema = [...userTableSchema, {key: "phone2", type: "number", required: false}]; await db.updateTable("user", newUserTableSchema);Update field
import Inibase from "inibase"; import { setField } from "inibase/utils"; const db = new Inibase("/databaseName"); const userTableSchema = (await db.getTable("user")).schema; setField("username", userTableSchema, {key: "fullName"}); await db.updateTable("user", newUserTableSchema);Remove field
import Inibase from "inibase"; import { unsetField } from "inibase/utils"; const db = new Inibase("/databaseName"); const userTableSchema = (await db.getTable("user")).schema; unsetField("fullName", userTableSchema); await db.updateTable("user", newUserTableSchema);Join Tables
import Inibase from "inibase"; const db = new Inibase("/databaseName"); const productTableSchema = [ { key: "title", type: "string", required: true, }, { key: "price", type: "number", }, { key: "createdBy", type: "table", table: "user", required: true, }, ]; await db.createTable("product", productTableSchema); const productTableData = [ { title: "Product 1", price: 16, createdBy: "1d88385d4b1581f8fb059334dec30f4c", }, { title: "Product 2", price: 10, createdBy: "5011c230aa44481bf7e8dcfe0710474f", }, ]; const product = await db.post("product", productTableData); // [ // { // "id": "1d88385d4b1581f8fb059334dec30f4c", // "title": "Product 1", // "price": 16, // "createdBy": { // "id": "1d88385d4b1581f8fb059334dec30f4c", // "username": "user1", // "email": "user1@example.com", // ... // } // }, // { // "id": "5011c230aa44481bf7e8dcfe0710474f", // "title": "Product 2", // "price": 10, // "createdBy": { // "id": "5011c230aa44481bf7e8dcfe0710474f", // "username": "user2", // ... // } // } // ]
POST
import Inibase from "inibase"; const db = new Inibase("/databaseName"); const userTableData = [ { username: "user1", email: "user1@example.com", age: 25, isActive: true, hobbies: [ { name: "Reading", level: "Intermediate" }, { name: "Cooking", level: "Beginner" }, ], favoriteFoods: ["Pizza", "Sushi", "Chocolate"], address: { street: "123 Main St", city: "Exampleville", country: "Sampleland", }, }, { username: "user2", email: "user2@example.com", age: 30, isActive: false, hobbies: [ { name: "Gardening", level: "Advanced" }, { name: "Photography", level: "Intermediate" }, ], favoriteFoods: ["Burgers", null, "Salad"], address: { street: "456 Elm Rd", city: "Testington", country: "Demo Country", }, }, ]; const users = await db.post("user", userTableData); // [ // { // "id": "1d88385d4b1581f8fb059334dec30f4c", // "username": "user1", // "email": "user1@example.com", // "age": 25, // "isActive": true, // "hobbies": { // "name": [ // "Reading", // "Cooking" // ], // "level": [ // "Intermediate", // "Beginner" // ] // }, // "favoriteFoods": [ // "Pizza", // "Sushi", // "Chocolate" // ], // "address": { // "street": "123 Main St", // "city": "Exampleville", // "country": "Sampleland" // } // }, // { // "id": "5011c230aa44481bf7e8dcfe0710474f", // "username": "user2", // ... // }, // ... // ]
GET
GET by ID
import Inibase from "inibase"; const db = new Inibase("/databaseName"); const user = await db.get("user", "1d88385d4b1581f8fb059334dec30f4c"); // { // "id": "1d88385d4b1581f8fb059334dec30f4c", // "username": "user1", // "email": "user1@example.com", // "age": 25, // "isActive": true, // "hobbies": { // "name": [ // "Reading", // "Cooking" // ], // "level": [ // "Intermediate", // "Beginner" // ] // }, // "favoriteFoods": [ // "Pizza", // "Sushi", // "Chocolate" // ], // "address": { // "street": "123 Main St", // "city": "Exampleville", // "country": "Sampleland" // } // }GET by criteria
import Inibase from "inibase"; const db = new Inibase("/databaseName"); const users = await db.get("user", { favoriteFoods: "[]Pizza" }); // [ // { // "id": "1d88385d4b1581f8fb059334dec30f4c", // "username": "user1", // "email": "user1@example.com", // "age": 25, // "isActive": true, // "hobbies": { // "name": [ // "Reading", // "Cooking" // ], // "level": [ // "Intermediate", // "Beginner" // ] // }, // "favoriteFoods": [ // "Pizza", // "Sushi", // "Chocolate" // ], // "address": { // "street": "123 Main St", // "city": "Exampleville", // "country": "Sampleland" // } // }, // ... // ]GET with columns
import Inibase from "inibase"; const db = new Inibase("/databaseName"); // Get all "user" columns except "username" & "address.street" const users = await db.get("user", undefined, { columns: ["!username", "!address.street"], });
PUT
import Inibase from "inibase"; const db = new Inibase("/databaseName"); // set "isActive" to "false" for all items in table "user" await db.put("user", { isActive: false }); // set "isActive" to "true" for specific "user" by id await db.put("user", { isActive: false }, "1d88385d4b1581f8fb059334dec30f4c"); // set "isActive" to "true" in table "user" by criteria (where "isActive" is equal to "true") await db.put("user", { isActive: false }, { isActive: true });
DELETE
import Inibase from "inibase"; const db = new Inibase("/databaseName"); // delete all items in "user" table await db.delete("user"); // delete a specific "user" by id await db.put("user", "1d88385d4b1581f8fb059334dec30f4c"); // delete "user" by criteria (where "isActive" is equal to "false") await db.put("user", { isActive: false });
SUM
import Inibase from "inibase"; const db = new Inibase("/databaseName"); // get the sum of column "age" in "user" table await db.sum("user", "age"); // get the sum of column "age" by criteria (where "isActive" is equal to "false") in "user" table await db.sum("user", ["age", ...], { isActive: false });
MAX
import Inibase from "inibase"; const db = new Inibase("/databaseName"); // get the biggest number of column "age" in "user" table await db.max("user", "age"); // get the biggest number of column "age" by criteria (where "isActive" is equal to "false") in "user" table await db.max("user", ["age", ...], { isActive: false });
MIN
import Inibase from "inibase"; const db = new Inibase("/databaseName"); // get the smallest number of column "age" in "user" table await db.min("user", "age"); // get the smallest number of column "age" by criteria (where "isActive" is equal to "false") in "user" table await db.min("user", ["age", ...], { isActive: false });
SORT
import Inibase from "inibase"; const db = new Inibase("/databaseName"); // order users by the age column await db.sort("user", "age"); // order users by the age and username columns await db.sort("user", ["age","username"]); await db.sort("user", {age: -1, username: "asc"});
10 | 100 | 1000 | |
---|---|---|---|
POST | 11 ms (0.65 mb) | 19 ms (1.00 mb) | 85 ms (4.58 mb) |
GET | 14 ms (2.77 mb) | 12 ms (3.16 mb) | 34 ms (1.38 mb) |
PUT | 6 ms (1.11 mb) | 5 ms (1.37 mb) | 10 ms (1.12 mb) |
DELETE | 17 ms (1.68 mb) | 14 ms (5.45 mb) | 25 ms (5.94 mb) |
10 | 100 | 1000 | |
---|---|---|---|
POST | 43 ms (4.70 mb) | 387 ms (6.36 mb) | 5341 ms (24.73 mb) |
GET | 99 ms (12.51 mb) | 846 ms (30.68 mb) | 7103 ms (30.86 mb) |
PUT | 33 ms (10.29 mb) | 312 ms (11.06 mb) | 3539 ms (14.87 mb) |
DELETE | 134 ms (13.50 mb) | 1224 ms (16.57 mb) | 7339 ms (11.46 mb) |
Testing by default with
user
table, with username, email, password fields so results include password encryption process
To run benchmarks, install typescript & tsx globally and runbenchmark
benchmark:bulk
benchmark:single
- [x] Actions:
- [x] GET:
- [x] Pagination
- [x] Criteria
- [x] Columns
- [x] Sort
- [x] POST
- [x] PUT
- [x] DELETE
- [x] SUM
- [x] MAX
- [x] MIN
- [x] GET:
- [ ] Schema supported types:
- [x] String
- [x] Number
- [x] Boolean
- [x] Date
- [x] Email
- [x] Url
- [x] Table
- [x] Object
- [x] Array
- [x] Password
- [x] IP
- [x] HTML
- [x] Id
- [x] JSON
- [ ] TO-DO:
- [x] Improve caching
- [ ] Commenting the code
- [x] Add property "unique" for schema fields
- [ ] Add Backup feature (generate a tar.gz)
- [ ] Add Custom field validation property to schema (using RegEx?)
- [ ] Features:
- [ ] Encryption
- [x] Data Compression
- [x] Caching System
- [ ] Suggest new feature +