1.0.0-rc.57 • Published 13 hours ago

inibase v1.0.0-rc.57

Weekly downloads
-
License
MIT
Repository
github
Last release
13 hours ago

Inibase banner

Inibase :pencil:

npmjs License Activity GitHub stars

A file-based & memory-efficient, serverless, ACID compliant, relational database management system :fire:

Features

  • Lightweight 🪶
  • Minimalist :white_circle: (but powerful)
  • 100% TypeScript :large_blue_diamond:
  • Super-Fast :zap: (built-in caching system)
  • ATOMIC :lock: File lock for writing
  • Built-in form-validation included :sunglasses:
  • Suitable for large data :page_with_curl: (tested with 200K row)
  • Support Compression :eight_spoked_asterisk: (using built-in nodejs zlib)
  • Support Table Joins :link:
  • Low memory-usage :chart_with_downwards_trend: (3-5mb)
  • Safe :lock: (no sql or javascript injections)
  • Easy to use :bread:
  • ... and much more :rocket:

Usage

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" });

If you like Inibase, please sponsor: GitHub Sponsors || Paypal.

Install

<npm|pnpm|yarn> install inibase

How it works?

To simplify the idea, each database has tables, each table has columns, each column will be stored in a seperated file. When POSTing new data, it will be appended to the head of each file as new line. When GETing data, the file will be readed line-by-line so it can handle large data (without consuming a lot of resources), when PUTing(updating) in a specific column, only one file will be opened and updated

Benchmark

Bulk

101001000
POST11 ms (0.65 mb)19 ms (1.00 mb)85 ms (4.58 mb)
GET14 ms (2.77 mb)12 ms (3.16 mb)34 ms (1.38 mb)
PUT6 ms (1.11 mb)5 ms (1.37 mb)10 ms (1.12 mb)
DELETE17 ms (1.68 mb)14 ms (5.45 mb)25 ms (5.94 mb)

Single

101001000
POST43 ms (4.70 mb)387 ms (6.36 mb)5341 ms (24.73 mb)
GET99 ms (12.51 mb)846 ms (30.68 mb)7103 ms (30.86 mb)
PUT33 ms (10.29 mb)312 ms (11.06 mb)3539 ms (14.87 mb)
DELETE134 ms (13.50 mb)1224 ms (16.57 mb)7339 ms (11.46 mb)

Ps: Testing by default with user table, with username, email, password fields so results include password encryption process

Config (.env)

The .env file supports the following parameters (make sure to run commands with flag --env-file=.env)

# Auto generated secret key, will be using for encrypting the IDs
INIBASE_SECRET=

INIBASE_COMPRESSION=true
INIBASE_CACHE=true

# Prepend new items to the beginning of file 
INIBASE_REVERSE=true

Roadmap

  • Actions:
    • GET:
      • Pagination
      • Criteria
      • Columns
      • Order By (using UNIX commands)
    • POST
    • PUT
    • DELETE
    • SUM
    • MAX
    • MIN
  • Schema supported types:
    • String
    • Number
    • Boolean
    • Date
    • Email
    • Url
    • Table
    • Object
    • Array
    • Password
    • IP
    • HTML
    • Id
    • JSON
  • TO-DO:
    • Improve caching
    • Commenting the code
    • Add property "unique" for schema fields
    • Add Backup feature (generate a tar.gz)
    • Add Custom field validation property to schema (using RegEx?)
  • Features:

Examples

import Inibase from "inibase";
const db = new Inibase("/databaseName");

const user_schema = [
  {
    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
      },
    ],
  },
];

const user_data = [
  {
    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", user_data);
// [
//   {
//     "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",
//     ...
//   },
//   ...
// ]

Link two tables: "product" with "user"

import Inibase from "inibase";
const db = new Inibase("/databaseName");

const product_schema = [
  {
    key: "title",
    type: "string",
    required: true,
  },
  {
    key: "price",
    type: "number",
  },
  {
    key: "createdBy",
    type: "table",
    table: "user",
    required: true,
  },
];

const product_data = [
  {
    title: "Product 1",
    price: 16,
    createdBy: "1d88385d4b1581f8fb059334dec30f4c",
  },
  {
    title: "Product 2",
    price: 10,
    createdBy: "5011c230aa44481bf7e8dcfe0710474f",
  },
];

const product = await db.post("product", product_data);
// [
//   {
//     "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",
//       ...
//     }
//   }
// ]
import Inibase from "inibase";
const db = new Inibase("/databaseName");

// Get "user" by id
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 "user" by Criteria: where "favoriteFoods" includes "Pizza"
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 all "user" columns except "username" & "address.street"
const users = await db.get("user", undefined, {
  columns: ["!username", "!address.street"],
});
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 });
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 });
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 });
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 });
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 });

License

MIT

1.0.0-rc.57

13 hours ago

1.0.0-rc.56

3 days ago

1.0.0-rc.55

8 days ago

1.0.0-rc.54

14 days ago

1.0.0-rc.53

15 days ago

1.0.0-rc.52

1 month ago

1.0.0-rc.51

1 month ago

1.0.0-rc.50

2 months ago

1.0.0-rc.49

2 months ago

1.0.0-rc.48

3 months ago

1.0.0-rc.47

3 months ago

1.0.0-rc.46

3 months ago

1.0.0-rc.45

3 months ago

1.0.0-rc.42

3 months ago

1.0.0-rc.44

3 months ago

1.0.0-rc.43

3 months ago

1.0.0-rc.40

4 months ago

1.0.0-rc.39

4 months ago

1.0.0-rc.38

4 months ago

1.0.0-rc.35

4 months ago

1.0.0-rc.34

4 months ago

1.0.0-rc.37

4 months ago

1.0.0-rc.36

4 months ago

1.0.0-rc.31

4 months ago

1.0.0-rc.33

4 months ago

1.0.0-rc.32

4 months ago

1.0.0-rc.29

4 months ago

1.0.0-rc.30

4 months ago

1.0.0-rc.28

4 months ago

1.0.0-rc.27

4 months ago

1.0.0-rc.26

5 months ago

1.0.0-rc.24

5 months ago

1.0.0-rc.25

5 months ago

1.0.0-rc.23

5 months ago

1.0.0-rc.20

5 months ago

1.0.0-rc.22

5 months ago

1.0.0-rc.21

5 months ago

1.0.0-rc.9

6 months ago

1.0.0-rc.7

7 months ago

1.0.0-rc.8

6 months ago

1.0.0-rc.13

6 months ago

1.0.0-rc.12

6 months ago

1.0.0-rc.11

6 months ago

1.0.0-rc.10

6 months ago

1.0.0-rc.17

5 months ago

1.0.0-rc.16

5 months ago

1.0.0-rc.15

6 months ago

1.0.0-rc.19

5 months ago

1.0.0-rc.18

5 months ago

1.0.0-rc.6

7 months ago

1.0.0-rc.5

7 months ago

1.0.0-rc.4

8 months ago

1.0.0-rc.3

8 months ago

1.0.0-rc.0

8 months ago

1.0.0-rc.2

8 months ago

1.0.0-rc.1

8 months ago

1.0.1

8 months ago

1.0.0

8 months ago