UNPKG

leaf-db

Version:

Small file-based database for node.js

314 lines (220 loc) 7.13 kB
<div align="center"> <img src="/assets/icon.svg" width="128" alt="leaf-db"> <h1>leaf-db</h1> <p><b>leaf-db</b> is a simple <a href="https://en.wikipedia.org/wiki/NoSQL">NoSQL</a> embeddable database for <a href="https://nodejs.org/en/">Node.js</a>.</p> </div> <div align="center"> <a href="/LICENSE"> <img alt="License GPLv3" src="https://img.shields.io/badge/license-GPLv3-blue.svg" /> </a> <a href="https://www.npmjs.com/package/leaf-db"> <img alt="NPM" src="https://img.shields.io/npm/v/leaf-db?label=npm"> </a> <a href="https://bundlephobia.com/result?p=leaf-db@latest"> <img alt="Bundle size" src="https://img.shields.io/bundlephobia/minzip/leaf-db@latest.svg"> </a> <a href="https://github.com/chronoDave/leaf-db/actions/workflows/ci.yml"> <img alt="CI" src="https://github.com/chronoDave/leaf-db/workflows/ci/badge.svg?branch=master"> </a> <a href="https://github.com/chronoDave/leaf-db/actions/workflows/codeql.yml"> <img alt="CodeQL" src="https://github.com/chronoDave/leaf-db/actions/workflows/codeql.yml/badge.svg?branch=master"> </a> </div> ## Features - **Strong-typed** documents and queries. - **Easy to embed** as it does not require an HTTP server to run. - Uses **JSON** documents. ## Table of Contents - [Getting started](#getting-started) - [Concepts](#concepts) - [Document](#document) - [Keys](#keys) - [Values](#values) - [Persistence](#persistence) - [Corruption](#corruption) - [Queries](#queries) - [Operators](#operators) - [API](#api) - [`id()`](#open) - [`open()`](#open) - [`close()`](#close) - [`insert()`](#insert) - [`select()`](#select) - [`selectById()`](#select-by-id) - [`update()`](#update) - [`delete()`](#delete) - [`drop()`](#drop) ## Getting Started ### Installation ```sh npm i leaf-db ``` ### Example Create a database using file storage with strong-typed documents: ```TS import LeafDB, { Draft } from 'leaf-db'; interface Document extends Draft { title: string name: string } // Use process.cwd() + 'db' as database root const db = new LeafDB<Document>('db'); db.open(); db.insert([ { title: 'Lady', name: 'Mipha' }, { title: 'Young Rito Warrior', name: 'Tulin' } ]); // [{ _id: <string>, title: 'Lady', name: 'Mipha' }] const characters = db.select({ title: 'Lady' }); ``` ## Concepts ### Document Leaf-db stores data as [JSON](https://www.json.org/json-en.html) documents. #### Keys Document keys must be of type `string` and cannot start with `$`. Every document is required to have an `_id` field. Leaf-db automatically creates an `_id` if the field does not exist on insertion. Keys have the following restrictions: - `_id` cannot be mutated once created. - `_id` must be unique. ### Values Leaf-db only supports JSON values, which are: - `object` - `array` - `string` - `number` - `true` - `false` - `null` ### Persistence Leaf-db stores the database in memory by default. To make use of persistence, simply provide a path in the constructor and open the database. ```TS import LeafDB from 'leaf-db'; /** * Create a new database under process.cwd() * This will create `db.txt` in process.cwd() */ const db = new LeafDB('db'); db.open(); ``` ### Corruption When opening a database from storage, leaf-db will return any documents that are corrupt. These documents will be deleted once opened. ```TS import LeafDB from 'leaf-db'; const db = new LeafDB('db'); // [] const corrupt = db.open(); ``` ### Queries Leaf-db supports both literal values and [operators](#operators). Example: ```TS /** * Literal query where value must equal the query value * { name: 'tulin' } // No match * { name: 'Mipha' } // No match */ const a = { name: 'Tulin' }; /** * Objects and arrays must be equal for it to match: * { eras: [] } // No match * { eras: ['era of the wilds'] } // No match * { eras: ['Era of the Wilds', 'Sky Era'] } // No match */ const b = { eras: ['Era of the Wilds'] } ``` #### Operators Operators allow for more complex queries. Operators must always be used in combination with values. For example: ```TS /** * Operator query where values must be greater than number */ const a = { age: { $gt: 3 } } ``` <b>Number operators</b>: - [`$gt`](#gt) - Is greater than - [`$gte`](#gte) - Is greater or equal than - [`$lt`](#lt) - Is less than - [`$lte`](#lte) - Is less or equal than <b>String operators</b>: - [`$text`](#text) - Includes string (case insensitive) - [`$regex`](#regex) - Matches RegExp <b>Array operators</b>: - [`$has`](#has) - Has value - [`$size`](#size) - Equal to size <b>Logic operators</b>: - [`$not`](#not) - Does not equal literal ## API ### `id()` Generate a new, unique id. ```TS import LeafDB from 'leaf-db'; const id = LeafDB.id(); ``` ### `open()` Open persistent storage. ```TS import LeafDB from 'leaf-db'; const db = new LeafDB('db'); // Draft[] const corrupted = db.open(); ``` ### `close()` Close persistent storage. ```TS import LeafDB from 'leaf-db'; const db = new LeafDB('db'); db.open(); db.close(); ``` ### `insert()` Insert document(s) into the database. Will throw an error if duplicate `_id`'s are found. ```TS import LeafDB from 'leaf-db'; const db = new LeafDB('db'); // [{ _id: <string>, name: 'Tulin' }, { _id: <string>, name: 'Mipha' }] const docs = db.insert([{ name: 'Tulin', }, { name: 'Mipha' }]); ``` ### `select()` Find document(s) based on [query](#queries). Multiple queries can be used. ```TS import LeafDB from 'leaf-db'; const db = new LeafDB('db'); // Return docs where `name` is equal to `Mipha` const docs = db.select({ name: 'Mipha' }); // Return docs where `name` is equal to `Mipha` or where `name` is equal to `Tulin` const docs = db.select({ name: 'Mipha' }, { name: 'Tulin' }); ``` ### `selectById()` Find document(s) based on `_id`. Multiple ids can be used. ```TS import LeafDB from 'leaf-db'; const db = new LeafDB('db'); // Return docs where `_id` is equal to `Mipha` const docs = db.selectById('Mipha'); // Return docs where `_id` is equal to `Mipha` or where `_id` is equal to `Tulin` const docs = db.selectById('Mipha', 'Tulin'); ``` ### `update()` Update document(s) based on [query](#queries). Multiple queries can be used. Updated document cannot change shape. ```TS import LeafDB from 'leaf-db'; const db = new LeafDB('db'); // Update docs where `name` is equal to `Tulin` and replace `name` with `Mipha` const docs = db.update({ name: 'Mipha' }, { name: 'Tulin' }); ``` ### `delete()` Delete document(s) based on [query](#queries). ```TS import LeafDB from 'leaf-db'; const db = new LeafDB('db'); // Delete docs where `name` is equal to `Mipha` const docs = db.delete({ name: 'Mipha' }); ``` ### `drop()` Delete all documents in the database. ```TS import LeafDB from 'leaf-db'; const db = new LeafDB('db'); db.drop(); ``` ## Acknowledgements - <div>Icon made by <a href="https://www.freepik.com" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a></div> - This project is inspired by [louischatriot/nedb](https://github.com/louischatriot/nedb).