Simple to use type-safe local JSON database 🦉
If you know JavaScript, you know how to use lowdb.
const db = await JSONFilePreset ( 'db.json' , { posts : [ ] } )
const post = { id : one , title : 'lowdb is awesome' , views : one hundred }
// In two steps
db . data . posts . push ( post )
await db . write ( )
// Or in one
await db . update ( ( { posts } ) => posts . push ( post ) )
// db.json
{
"posts" : [
{ "id" : one , "title" : "lowdb is awesome" , "views" : one hundred }
]
}
const { posts } = db . data
posts . at ( zero ) // First post
posts . filter ( ( post ) => post . title . includes ( 'lowdb' ) ) // Filter by title
posts . find ( ( post ) => post . id === one ) // Find by id
posts . toSorted ( ( a , b ) => a . views - b . views ) // Sort by views
-
Lightweight -
Minimalist -
TypeScript -
Plain JavaScript -
Safe atomic writes -
Hackable: -
Change storage, file format (JSON, YAML, ...) or add encryption via adapters -
Extend it with lodash, ramda, ... for super powers!
-
-
Automatically switches to fast in-memory mode during tests
npm install lowdb
import { JSONFilePreset } from 'lowdb/node'
// Read or create db.json
const defaultData = { posts : [ ] }
const db = await JSONFilePreset ( 'db.json' , defaultData )
// Update db.json
await db . update ( ( { posts } ) => posts . push ( 'hello world' ) )
// Alternatively you can call db.write() explicitely later
// to write to db.json
db . data . posts . push ( 'hello world' )
await db . write ( )
// db.json
{
"posts" : [ "hello world" ]
}
type Data = {
messages : string [ ]
}
const defaultData : Data = { messages : [ ] }
const db = await JSONPreset < Data > ( 'db.json' , defaultData )
db . data . messages . push ( 'foo' ) // ✅ Success
db . data . messages . push ( one ) // ❌ TypeScript error
import { Low } from 'lowdb'
import { JSONFile } from 'lowdb/node'
import lodash from 'lodash'
type Post = {
id : number
title : string
}
type Data = {
posts : Post [ ]
}
// Extend Low class with a new `chain` field
class LowWithLodash < T > extends Low < T > {
chain : lodash . ExpChain < this [ 'data' ] > = lodash . chain ( this ) . get ( 'data' )
}
const defaultData : Data = {
posts : [ ] ,
}
const adapter = new JSONFile < Data > ( 'db.json' , defaultData )
const db = new LowWithLodash ( adapter )
await db . read ( )
// Instead of db.data use db.chain to access lodash API
const post = db . chain . get ( 'posts' ) . find ( { id : one } ) . value ( ) // Important: value() must be called to execute chain
JSONFilePreset(filename, defaultData) JSONFileSyncPreset(filename, defaultData) LocalStoragePreset(name, defaultData) SessionStoragePreset(name, defaultData)
import { Low } from 'lowdb'
import { JSONFile } from 'lowdb/node'
const db = new Low ( new JSONFile ( 'file.json' ) , { } )
await db . read ( )
await db . write ( )
import { LowSync } from 'lowdb'
import { JSONFileSync } from 'lowdb/node'
const db = new LowSync ( new JSONFileSync ( 'file.json' ) , { } )
db . read ( )
db . write ( )
db . data // === null
db . read ( )
db . data // !== null
db . data = { posts : [ ] }
db . write ( ) // file.json will be { posts: [] }
db . data = { }
db . write ( ) // file.json will be {}
db . update ( ( data ) => {
// make changes to data
// ...
} )
// files.json will be updated
db . data = 'string'
db . data = [ one , two , three ]
db . data = { key : 'value' }
import { JSONFile , JSONFileSync } from 'lowdb/node'
new Low ( new JSONFile ( filename ) , { } )
new LowSync ( new JSONFileSync ( filename ) , { } )
import { Memory , MemorySync } from 'lowdb'
new Low ( new Memory ( ) , { } )
new LowSync ( new MemorySync ( ) , { } )
import { LocalStorage , SessionStorage } from 'lowdb/browser'
new LowSync ( new LocalStorage ( name ) , { } )
new LowSync ( new SessionStorage ( name ) , { } )
import { DataFile } from 'lowdb/node'
new DataFile ( filename , {
parse : YAML . parse ,
stringify : YAML . stringify
} )
new DataFile ( filename , {
parse : ( data ) => { decypt ( JSON . parse ( data ) ) } ,
stringify : ( str ) => { encrypt ( JSON . stringify ( str ) ) }
} )
class AsyncAdapter {
read ( ) {
/* ... */
} // should return Promise<data>
write ( data ) {
/* ... */
} // should return Promise<void>
}
class SyncAdapter {
read ( ) {
/* ... */
} // should return data
write ( data ) {
/* ... */
} // should return nothing
}
import { Low } from 'lowdb'
import { api } from './ AsyncStorage'
class CustomAsyncAdapter {
// Optional: your adapter can take arguments
constructor ( args ) {
// ...
}
async read ( ) {
const data = await api . read ( )
return data
}
async write ( data ) {
await api . write ( data )
}
}
const adapter = new CustomAsyncAdapter ( )
const db = new Low ( adapter , { } )
import { Adapter , Low } from 'lowdb'
import { TextFile } from 'lowdb/node'
import YAML from 'yaml'
class YAMLFile {
constructor ( filename ) {
this . adapter = new TextFile ( filename )
}
async read ( ) {
const data = await this . adapter . read ( )
if ( data === null ) {
return null
} else {
return YAML . parse ( data )
}
}
write ( obj ) {
return this . adapter . write ( YAML . stringify ( obj ) )
}
}
const adapter = new YAMLFile ( 'file.yaml' )
const db = new Low ( adapter , { } )