UNPKG

7.82 kBMarkdownView Raw
1# lowdb [![](http://img.shields.io/npm/dm/lowdb.svg?style=flat)](https://www.npmjs.org/package/lowdb) [![Node.js CI](https://github.com/typicode/lowdb/actions/workflows/node.js.yml/badge.svg)](https://github.com/typicode/lowdb/actions/workflows/node.js.yml)
2
3> Simple to use local JSON database. Use native JavaScript API to query. Written in TypeScript. 🦉
4
5```js
6// Edit db.json content using native JS API
7db.data
8 .posts
9 .push({ id: 1, title: 'lowdb is awesome' })
10
11// Save to file
12db.write()
13```
14
15```js
16// db.json
17{
18 "posts": [
19 { "id": 1, "title": "lowdb is awesome" }
20 ]
21}
22```
23
24If you like lowdb, see also [xv](https://github.com/typicode/xv) (test runner) and [steno](https://github.com/typicode/steno) (fast file writer).
25
26## Sponsors
27
28<br>
29<br>
30
31<p align="center">
32 <a href="https://mockend.com/" target="_blank">
33 <img src="https://jsonplaceholder.typicode.com/mockend.svg" height="70px">
34 </a>
35</p>
36
37<br>
38<br>
39
40[Become a sponsor and have your company logo here](https://github.com/sponsors/typicode).
41
42Please help me build OSS 👉 [GitHub Sponsors](https://github.com/sponsors/typicode)
43
44## Features
45
46- __Lightweight__
47- __Minimalist__
48- __TypeScript__
49- __plain JS__
50- Atomic write
51- Hackable:
52 - Change storage, file format (JSON, YAML, ...) or add encryption via [adapters](#adapters)
53 - Add lodash, ramda, ... for super powers!
54
55## Install
56
57```sh
58npm install lowdb
59```
60
61## Usage
62
63_Lowdb is a pure ESM package. If you're having trouble importing it in your project, please [read this](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c)._
64
65```js
66import { join, dirname } from 'node:path'
67import { fileURLToPath } from 'node:url'
68
69import { Low } from 'lowdb'
70import { JSONFile } from 'lowdb/node'
71
72// File path
73const __dirname = dirname(fileURLToPath(import.meta.url));
74const file = join(__dirname, 'db.json')
75
76// Configure lowdb to write to JSONFile
77const adapter = new JSONFile(file)
78const db = new Low(adapter)
79
80// Read data from JSON file, this will set db.data content
81await db.read()
82
83// If db.json doesn't exist, db.data will be null
84// Use the code below to set default data
85// db.data = db.data || { posts: [] } // For Node < v15.x
86db.data ||= { posts: [] } // For Node >= 15.x
87
88// Create and query items using native JS API
89db.data.posts.push('hello world')
90const firstPost = db.data.posts[0]
91
92// Alternatively, you can also use this syntax if you prefer
93const { posts } = db.data
94posts.push('hello world')
95
96// Finally write db.data content to file
97await db.write()
98```
99
100```js
101// db.json
102{
103 "posts": [ "hello world" ]
104}
105```
106
107### TypeScript
108
109You can use TypeScript to check your data types.
110
111```ts
112type Data = {
113 words: string[]
114}
115
116const adapter = new JSONFile<Data>('db.json')
117const db = new Low(adapter)
118
119db.data
120 .words
121 .push('foo') // ✅ Success
122
123db.data
124 .words
125 .push(1) // ❌ TypeScript error
126```
127
128### Lodash
129
130You can also add lodash or other utility libraries to improve lowdb.
131
132```ts
133import lodash from 'lodash'
134
135type Post = {
136 id: number;
137 title: string;
138}
139
140type Data = {
141 posts: Post[]
142}
143
144// Extend Low class with a new `chain` field
145class LowWithLodash<T> extends Low<T> {
146 chain: lodash.ExpChain<this['data']> = lodash.chain(this).get('data')
147}
148
149const adapter = new JSONFile<Data>('db.json')
150const db = new LowWithLodash(adapter)
151await db.read()
152
153// Instead of db.data use db.chain to access lodash API
154const post = db.chain
155 .get('posts')
156 .find({ id: 1 })
157 .value() // Important: value() must be called to execute chain
158```
159
160### CLI, Server and Browser usage
161
162See [`examples/`](/examples) directory.
163
164## API
165
166### Classes
167
168Lowdb has two classes (for asynchronous and synchronous adapters).
169
170#### `new Low(adapter)`
171
172```js
173import { Low } from 'lowdb'
174import { JSONFile } from 'lowdb/node'
175
176const db = new Low(new JSONFile('file.json'))
177await db.read()
178await db.write()
179```
180
181#### `new LowSync(adapterSync)`
182
183```js
184import { LowSync } from 'lowdb'
185import { JSONFileSync } from 'lowdb/node'
186
187const db = new LowSync(new JSONFileSync('file.json'))
188db.read()
189db.write()
190```
191
192### Methods
193
194#### `db.read()`
195
196Calls `adapter.read()` and sets `db.data`.
197
198**Note:** `JSONFile` and `JSONFileSync` adapters will set `db.data` to `null` if file doesn't exist.
199
200```js
201db.data // === null
202db.read()
203db.data // !== null
204```
205
206#### `db.write()`
207
208Calls `adapter.write(db.data)`.
209
210```js
211db.data = { posts: [] }
212db.write() // file.json will be { posts: [] }
213db.data = {}
214db.write() // file.json will be {}
215```
216
217### Properties
218
219#### `db.data`
220
221Holds your db content. If you're using the adapters coming with lowdb, it can be any type supported by [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
222
223For example:
224
225```js
226db.data = 'string'
227db.data = [1, 2, 3]
228db.data = { key: 'value' }
229```
230
231## Adapters
232
233### Lowdb adapters
234
235#### `JSONFile` `JSONFileSync`
236
237Adapters for reading and writing JSON files.
238
239```js
240import { JSONFile, JSONFileSync } from 'lowdb/node'
241
242new Low(new JSONFile(filename))
243new LowSync(new JSONFileSync(filename))
244```
245
246#### `Memory` `MemorySync`
247
248In-memory adapters. Useful for speeding up unit tests. See [`examples/`](/examples) directory.
249
250
251```js
252import { Memory, MemorySync } from 'lowdb'
253
254new Low(new Memory())
255new LowSync(new MemorySync())
256```
257
258#### `LocalStorage`
259
260Synchronous adapter for `window.localStorage`.
261
262```js
263import { LocalStorage } from 'lowdb/browser'
264
265new LowSync(new LocalStorage(name))
266```
267
268#### `TextFile` `TextFileSync`
269
270Adapters for reading and writing text. Useful for creating custom adapters.
271
272### Third-party adapters
273
274If you've published an adapter for lowdb, feel free to create a PR to add it here.
275
276### Writing your own adapter
277
278You may want to create an adapter to write `db.data` to YAML, XML, encrypt data, a remote storage, ...
279
280An adapter is a simple class that just needs to expose two methods:
281
282```js
283class AsyncAdapter {
284 read() { /* ... */ } // should return Promise<data>
285 write(data) { /* ... */ } // should return Promise<void>
286}
287
288class SyncAdapter {
289 read() { /* ... */ } // should return data
290 write(data) { /* ... */ } // should return nothing
291}
292```
293
294For example, let's say you have some async storage and want to create an adapter for it:
295
296```js
297import { api } from './AsyncStorage'
298
299class CustomAsyncAdapter {
300 // Optional: your adapter can take arguments
301 constructor(args) {
302 // ...
303 }
304
305 async read() {
306 const data = await api.read()
307 return data
308 }
309
310 async write(data) {
311 await api.write(data)
312 }
313}
314
315const adapter = new CustomAsyncAdapter()
316const db = new Low(adapter)
317```
318
319See [`src/adapters/`](src/adapters) for more examples.
320
321#### Custom serialization
322
323To create an adapter for another format than JSON, you can use `TextFile` or `TextFileSync`.
324
325For example:
326
327```js
328import { Adapter, Low } from 'lowdb'
329import { TextFile } from 'lowdb/node'
330import YAML from 'yaml'
331
332class YAMLFile {
333 constructor(filename) {
334 this.adapter = new TextFile(filename)
335 }
336
337 async read() {
338 const data = await this.adapter.read()
339 if (data === null) {
340 return null
341 } else {
342 return YAML.parse(data)
343 }
344 }
345
346 write(obj) {
347 return this.adapter.write(YAML.stringify(obj))
348 }
349}
350
351const adapter = new YAMLFile('file.yaml')
352const db = new Low(adapter)
353```
354
355## Limits
356
357Lowdb doesn't support Node's cluster module.
358
359If you have large JavaScript objects (`~10-100MB`) you may hit some performance issues. This is because whenever you call `db.write`, the whole `db.data` is serialized using `JSON.stringify` and written to storage.
360
361Depending on your use case, this can be fine or not. It can be mitigated by doing batch operations and calling `db.write` only when you need it.
362
363If you plan to scale, it's highly recommended to use databases like PostgreSQL or MongoDB instead.