### Example db.json Content Source: https://github.com/typicode/lowdb/blob/main/README.md Illustrates the structure of the db.json file after adding a post. ```json { "posts": [ { "id": 1, "title": "lowdb is awesome", "views": 100 } ] } ``` -------------------------------- ### Example db.json after update Source: https://github.com/typicode/lowdb/blob/main/README.md Shows the content of `db.json` after adding 'hello world' to the posts array. ```json { "posts": [ "hello world" ] } ``` -------------------------------- ### Install lowdb Source: https://github.com/typicode/lowdb/blob/main/README.md Command to install the lowdb package using npm. ```sh npm install lowdb ``` -------------------------------- ### Async JSON File Database with Preset Source: https://context7.com/typicode/lowdb/llms.txt Use JSONFilePreset for a quick setup of an async JSON database. It handles reading existing data, providing defaults, and automatically uses an in-memory adapter for tests. ```typescript import { JSONFilePreset } from 'lowdb/node' type Post = { id: number; title: string; views: number } type Data = { posts: Post[] } // Read or create db.json with default data const db = await JSONFilePreset('db.json', { posts: [] }) // Insert a record await db.update(({ posts }) => posts.push({ id: 1, title: 'Hello lowdb', views: 0 })) // Query with native array methods const { posts } = db.data const post = posts.find((p) => p.id === 1) // { id: 1, title: 'Hello lowdb', views: 0 } const popular = posts.filter((p) => p.views > 100) // [] const sorted = posts.toSorted((a, b) => b.views - a.views) // Direct mutation + explicit write db.data.posts[0].views += 1 await db.write() // db.json on disk: // { // "posts": [ // { "id": 1, "title": "Hello lowdb", "views": 1 } // ] // } ``` -------------------------------- ### Build Express.js REST API with lowdb Source: https://context7.com/typicode/lowdb/llms.txt This snippet demonstrates setting up an Express server with lowdb for CRUD operations on posts. It includes routes for GET, POST, and DELETE requests. Ensure lowdb and express are installed. ```typescript import express from 'express' import asyncHandler from 'express-async-handler' import { JSONFilePreset } from 'lowdb/node' const app = express() app.use(express.json()) type Post = { id: string; body: string } type Data = { posts: Post[] } const db = await JSONFilePreset('db.json', { posts: [] }) const { posts } = db.data // GET /posts/:id app.get('/posts/:id', (req, res) => { const post = posts.find((p) => p.id === req.params.id) if (!post) return res.status(404).json({ error: 'Not found' }) res.json(post) }) // POST /posts — body: { body: string } app.post('/posts', asyncHandler(async (req, res) => { const post: Post = { id: String(posts.length + 1), body: req.body.body } await db.update(({ posts }) => posts.push(post)) res.status(201).json(post) })) // DELETE /posts/:id app.delete('/posts/:id', asyncHandler(async (req, res) => { await db.update((data) => { const idx = data.posts.findIndex((p) => p.id === req.params.id) if (idx !== -1) data.posts.splice(idx, 1) }) res.status(204).send() })) app.listen(3000, () => console.log('Listening on http://localhost:3000')) // curl -X POST http://localhost:3000/posts -H 'Content-Type: application/json' -d '{"body":"Hello"}' // → { "id": "1", "body": "Hello" } // curl http://localhost:3000/posts/1 // → { "id": "1", "body": "Hello" } ``` -------------------------------- ### Async Database Class with Custom Adapter and Lodash Source: https://context7.com/typicode/lowdb/llms.txt The Low class is the foundational async database class, accepting any adapter. This example extends it to include lodash chaining for complex queries and demonstrates atomic updates. ```typescript 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 to add lodash chaining class LowWithLodash extends Low { chain: lodash.ExpChain = lodash.chain(this).get('data') } const adapter = new JSONFile('db.json') const db = new LowWithLodash(adapter, { posts: [] }) await db.read() // Use lodash chain for complex queries const firstPost = db.chain.get('posts').find({ id: 1 }).value() const titles = db.chain.get('posts').map('title').sort().value() // Mutate then write db.data.posts.push({ id: 2, title: 'Second post' }) await db.write() // Or use update() for atomic mutate + write await db.update(({ posts }) => { const post = posts.find((p) => p.id === 1) if (post) post.title = 'Updated title' }) ``` -------------------------------- ### Custom Async Adapter for Remote API Source: https://context7.com/typicode/lowdb/llms.txt Implement the Adapter interface with read() and write() methods to use Low with any asynchronous data source, such as a REST API. This example demonstrates an adapter for a remote API using fetch. ```typescript import { Low, Adapter } from 'lowdb' type AppData = { settings: Record } // Adapter backed by a REST API class RemoteAdapter implements Adapter { #url: string #token: string constructor(url: string, token: string) { this.#url = url this.#token = token } async read(): Promise { const res = await fetch(this.#url, { headers: { Authorization: `Bearer ${this.#token}` }, }) if (res.status === 404) return null if (!res.ok) throw new Error(`Read failed: ${res.statusText}`) return res.json() as Promise } async write(data: AppData): Promise { const res = await fetch(this.#url, { method: 'PUT', headers: { Authorization: `Bearer ${this.#token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(data), }) if (!res.ok) throw new Error(`Write failed: ${res.statusText}`) } } const db = new Low(new RemoteAdapter('https://api.example.com/store/1', 'my-token'), { settings: {} }) await db.read() await db.update((data) => { data.settings['darkMode'] = true }) ``` -------------------------------- ### Initialize LowSync with JSONFileSync Adapter Source: https://github.com/typicode/lowdb/blob/main/README.md Demonstrates the synchronous version of initializing lowdb using `LowSync` and `JSONFileSync`. This is suitable for environments where asynchronous operations are not desired or possible. ```javascript import { LowSync } from 'lowdb' import { JSONFileSync } from 'lowdb/node' const db = new LowSync(new JSONFileSync('file.json'), {}) // {} is the defaultData db.read() db.write() ``` -------------------------------- ### Initialize Low with JSONFile Adapter Source: https://github.com/typicode/lowdb/blob/main/README.md Shows how to instantiate the `Low` class with a `JSONFile` adapter for asynchronous operations. This is a more fundamental approach than using presets. ```javascript import { Low } from 'lowdb' import { JSONFile } from 'lowdb/node' const db = new Low(new JSONFile('file.json'), {}) // {} is the defaultData await db.read() await db.write() ``` -------------------------------- ### Initialize and Set Defaults for Lowdb Source: https://github.com/typicode/lowdb/wiki/Example-of-batching-to-one-write Initializes the Lowdb database with a file adapter and sets default values. Ensure defaults are set if the JSON file might be empty. ```javascript const lodash = require('lodash'); const low = require('lowdb'); const FileAsync = require('lowdb/adapters/FileAsync'); let db; let results; async function run() { db = await low(new FileAsync('results.json')); // Set some defaults (required if your JSON file is empty) await db .defaults({ results: [] }) .value(); results = await db.get('results', []); } ``` -------------------------------- ### Initialize JSONFile and JSONFileSync Adapters Source: https://github.com/typicode/lowdb/blob/main/README.md Use `JSONFile` or `JSONFileSync` for reading and writing JSON files. Initialize `Low` or `LowSync` with the adapter and an initial empty data object. ```javascript import { JSONFile, JSONFileSync } from 'lowdb/node' new Low(new JSONFile(filename), {}) new LowSync(new JSONFileSync(filename), {}) ``` -------------------------------- ### Initialize LocalStorage and SessionStorage Adapters Source: https://github.com/typicode/lowdb/blob/main/README.md Use `LocalStorage` or `SessionStorage` for synchronous adapters with `window.localStorage` and `window.sessionStorage`. Initialize `LowSync` with the adapter and an initial data object. ```javascript import { LocalStorage, SessionStorage } from 'lowdb/browser' new LowSync(new LocalStorage(name), {}) new LowSync(new SessionStorage(name), {}) ``` -------------------------------- ### Basic Usage with JSONFilePreset Source: https://github.com/typicode/lowdb/blob/main/README.md Imports `JSONFilePreset` and demonstrates reading/creating `db.json`, updating data, and writing changes. Note that lowdb is a pure ESM package. ```javascript 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() ``` -------------------------------- ### Initialize Memory and MemorySync Adapters Source: https://github.com/typicode/lowdb/blob/main/README.md Use `Memory` or `MemorySync` for in-memory storage, which is useful for speeding up unit tests. Initialize `Low` or `LowSync` with the adapter and an initial data object. ```javascript import { Memory, MemorySync } from 'lowdb' new Low(new Memory(), {}) new LowSync(new MemorySync(), {}) ``` -------------------------------- ### JSONFilePreset Source: https://context7.com/typicode/lowdb/llms.txt Quickly create an async JSON file database. It reads existing data, falls back to default data if the file doesn't exist, and switches to an in-memory adapter for tests. ```APIDOC ## `JSONFilePreset(filename, defaultData)` ### Description The simplest way to get started with lowdb on Node.js. Automatically reads existing data from the file if present, falls back to `defaultData` when the file does not exist, and transparently switches to an in-memory adapter when `NODE_ENV=test` to speed up tests with zero configuration changes. ### Usage ```ts import { JSONFilePreset } from 'lowdb/node' type Post = { id: number; title: string; views: number } type Data = { posts: Post[] } // Read or create db.json with default data const db = await JSONFilePreset('db.json', { posts: [] }) // Insert a record await db.update(({ posts }) => posts.push({ id: 1, title: 'Hello lowdb', views: 0 })) // Query with native array methods const { posts } = db.data const post = posts.find((p) => p.id === 1) // { id: 1, title: 'Hello lowdb', views: 0 } const popular = posts.filter((p) => p.views > 100) // [] const sorted = posts.toSorted((a, b) => b.views - a.views) // Direct mutation + explicit write db.data.posts[0].views += 1 await db.write() ``` ### Example File Content ```json { "posts": [ { "id": 1, "title": "Hello lowdb", "views": 1 } ] } ``` ``` -------------------------------- ### Initialize JSONFilePreset Source: https://github.com/typicode/lowdb/blob/main/README.md Reads or creates a db.json file with default data. Ensure the file exists or will be created with the provided default structure. ```javascript const db = await JSONFilePreset('db.json', { posts: [] }) ``` -------------------------------- ### Read and Access Data with db.read() Source: https://github.com/typicode/lowdb/blob/main/README.md Use `db.read()` to fetch data from the adapter and populate `db.data`. If the file does not exist, `db.data` will be set to `null`. ```javascript db.data // === null db.read() db.data // !== null ``` -------------------------------- ### Browser Presets Source: https://context7.com/typicode/lowdb/llms.txt Convenience factory functions for browser storage that construct a `LowSync` instance, read existing data, and return a ready-to-use database in one call. ```APIDOC ## `LocalStoragePreset(key, defaultData)` / `SessionStoragePreset(key, defaultData)` — Browser presets Convenience factory functions for browser storage. Construct a `LowSync` instance backed by `localStorage` or `sessionStorage`, read existing data, and return the ready-to-use database in one call. ```ts import { LocalStoragePreset, SessionStoragePreset } from 'lowdb/browser' type Preferences = { theme: 'light' | 'dark'; lang: string } const prefs = LocalStoragePreset('prefs', { theme: 'light', lang: 'en' }) prefs.update((data) => { data.theme = 'dark' }) console.log(prefs.data.theme) // 'dark' type Draft = { title: string; body: string } const draft = SessionStoragePreset('draft', { title: '', body: '' }) draft.update((data) => { data.title = 'My draft'; data.body = 'Work in progress...' }) ``` ``` -------------------------------- ### Low Source: https://context7.com/typicode/lowdb/llms.txt The foundational async database class. Accepts any object implementing the `Adapter` interface and provides `read()`, `write()`, and `update()` methods. Use this directly for custom adapters or fine-grained control. ```APIDOC ## `new Low(adapter, defaultData)` ### Description The foundational async class. Accepts any object implementing the `Adapter` interface. Provides `read()`, `write()`, and `update()` methods. Use this directly when you need a custom adapter or want fine-grained control over reads and writes. ### Usage ```ts 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 to add lodash chaining class LowWithLodash extends Low { chain: lodash.ExpChain = lodash.chain(this).get('data') } const adapter = new JSONFile('db.json') const db = new LowWithLodash(adapter, { posts: [] }) await db.read() // Use lodash chain for complex queries const firstPost = db.chain.get('posts').find({ id: 1 }).value() const titles = db.chain.get('posts').map('title').sort().value() // Mutate then write db.data.posts.push({ id: 2, title: 'Second post' }) await db.write() // Or use update() for atomic mutate + write await db.update(({ posts }) => { const post = posts.find((p) => p.id === 1) if (post) post.title = 'Updated title' }) ``` ``` -------------------------------- ### Implement Custom YAMLFile Adapter for Lowdb Source: https://github.com/typicode/lowdb/blob/main/README.md Create a custom adapter for YAML files by combining `TextFile` with YAML parsing and stringifying functions. This allows lowdb to read and write YAML data. ```javascript 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, {}) ``` -------------------------------- ### JSONFile / JSONFileSync Source: https://context7.com/typicode/lowdb/llms.txt Low-level adapters for reading and writing JSON files. JSONFile uses async I/O, while JSONFileSync uses sync I/O. ```APIDOC ## `new JSONFile(filename)` / `new JSONFileSync(filename)` — JSON file adapters Low-level adapters that read and write JSON files. `JSONFile` uses async I/O with `steno` for atomic writes; `JSONFileSync` uses synchronous I/O with a temp-file rename strategy to prevent corruption. Both pretty-print JSON with 2-space indentation. ```ts import { Low, LowSync } from 'lowdb' import { JSONFile, JSONFileSync } from 'lowdb/node' // Async const asyncAdapter = new JSONFile<{ items: string[] }>('data.json') const asyncDb = new Low(asyncAdapter, { items: [] }) await asyncDb.read() asyncDb.data.items.push('apple') await asyncDb.write() // data.json → { "items": ["apple"] } // Sync const syncAdapter = new JSONFileSync<{ items: string[] }>('data-sync.json') const syncDb = new LowSync(syncAdapter, { items: [] }) syncDb.read() syncDb.data.items.push('banana') syncDb.write() // data-sync.json → { "items": ["banana"] } ``` ``` -------------------------------- ### Custom YAML Adapter using TextFile Source: https://context7.com/typicode/lowdb/llms.txt Demonstrates building a custom YAML adapter by extending TextFile. This approach can be used for any non-JSON text-based format. ```typescript import { Low } from 'lowdb' import { TextFile } from 'lowdb/node' import YAML from 'yaml' // Build a YAML adapter using TextFile class YAMLFile { #adapter: TextFile constructor(filename: string) { this.#adapter = new TextFile(filename) } async read(): Promise { const text = await this.#adapter.read() return text === null ? null : (YAML.parse(text) as T) } write(obj: T): Promise { return this.#adapter.write(YAML.stringify(obj)) } } type Config = { host: string; port: number } const db = new Low(new YAMLFile('config.yaml'), { host: 'localhost', port: 3000 }) await db.read() await db.update((data) => { data.port = 8080 }) // config.yaml: // host: localhost // port: 8080 ``` -------------------------------- ### Async and Sync JSON File Adapters Source: https://context7.com/typicode/lowdb/llms.txt Use JSONFile for asynchronous operations and JSONFileSync for synchronous operations. Both pretty-print JSON with 2-space indentation. ```typescript import { Low, LowSync } from 'lowdb' import { JSONFile, JSONFileSync } from 'lowdb/node' // Async const asyncAdapter = new JSONFile<{ items: string[] }>('data.json') const asyncDb = new Low(asyncAdapter, { items: [] }) await asyncDb.read() asyncDb.data.items.push('apple') await asyncDb.write() // data.json → { "items": ["apple"] } // Sync const syncAdapter = new JSONFileSync<{ items: string[] }>('data-sync.json') const syncDb = new LowSync(syncAdapter, { items: [] }) syncDb.read() syncDb.data.items.push('banana') syncDb.write() // data-sync.json → { "items": ["banana"] } ``` -------------------------------- ### Create Custom SyncAdapter for Lowdb Source: https://github.com/typicode/lowdb/blob/main/README.md Define a custom synchronous adapter by implementing `read()` and `write()` methods. This is suitable for synchronous storage operations. ```javascript class SyncAdapter { read() { /* ... */ } // should return data write(data) { /* ... */ } // should return nothing } ``` -------------------------------- ### Define Custom AsyncAdapter for Lowdb Source: https://github.com/typicode/lowdb/blob/main/README.md Create a custom asynchronous adapter by implementing `read()` and `write()` methods that return Promises. This allows integration with asynchronous storage solutions. ```javascript 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, {}) ``` -------------------------------- ### Create Custom DataFile Adapters Source: https://github.com/typicode/lowdb/blob/main/README.md Use `DataFile` to support custom data formats or add behaviors like encryption. Provide `parse` and `stringify` functions to handle the data transformation. ```javascript 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)) } }) ``` -------------------------------- ### Custom Async Adapter Source: https://context7.com/typicode/lowdb/llms.txt Implement the `Adapter` interface to create custom asynchronous adapters for data sources like REST APIs or cloud storage. These adapters must implement `read(): Promise` and `write(data: T): Promise`. ```APIDOC ## Custom async adapter — Implementing the `Adapter` interface Any class that implements `read(): Promise` and `write(data: T): Promise` can be used with `Low`. This allows targeting remote APIs, cloud storage, databases, or any async data source. ```ts import { Low, Adapter } from 'lowdb' type AppData = { settings: Record } // Adapter backed by a REST API class RemoteAdapter implements Adapter { #url: string #token: string constructor(url: string, token: string) { this.#url = url this.#token = token } async read(): Promise { const res = await fetch(this.#url, { headers: { Authorization: `Bearer ${this.#token}` }, }) if (res.status === 404) return null if (!res.ok) throw new Error(`Read failed: ${res.statusText}`) return res.json() as Promise } async write(data: AppData): Promise { const res = await fetch(this.#url, { method: 'PUT', headers: { Authorization: `Bearer ${this.#token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(data), }) if (!res.ok) throw new Error(`Write failed: ${res.statusText}`) } } const db = new Low(new RemoteAdapter('https://api.example.com/store/1', 'my-token'), { settings: {} }) await db.read() await db.update((data) => { data.settings['darkMode'] = true }) ``` ``` -------------------------------- ### Browser Storage Preset Factory Functions Source: https://context7.com/typicode/lowdb/llms.txt Convenience functions LocalStoragePreset and SessionStoragePreset construct a LowSync instance, read data, and return a ready-to-use database in one call. They accept a key and default data. ```typescript import { LocalStoragePreset, SessionStoragePreset } from 'lowdb/browser' type Preferences = { theme: 'light' | 'dark'; lang: string } const prefs = LocalStoragePreset('prefs', { theme: 'light', lang: 'en' }) prefs.update((data) => { data.theme = 'dark' }) console.log(prefs.data.theme) // 'dark' type Draft = { title: string; body: string } const draft = SessionStoragePreset('draft', { title: '', body: '' }) draft.update((data) => { data.title = 'My draft'; data.body = 'Work in progress...' }) ``` -------------------------------- ### Sync JSON File Database with Preset Source: https://context7.com/typicode/lowdb/llms.txt JSONFileSyncPreset offers a synchronous alternative for JSON file databases, ideal for CLI tools. It also defaults to an in-memory adapter during tests. ```typescript import { JSONFileSyncPreset } from 'lowdb/node' type Data = { messages: string[] } const db = JSONFileSyncPreset('file.json', { messages: [] }) // Append a message passed via CLI argument const message = process.argv[2] ?? 'default message' db.update(({ messages }) => messages.push(message)) // file.json after running: node cli.js "Hello" // { "messages": ["Hello"] } ``` -------------------------------- ### Browser Web Storage Adapters Source: https://context7.com/typicode/lowdb/llms.txt Synchronous adapters for `window.localStorage` and `window.sessionStorage`. These adapters serialize JSON data to a single storage key and are used with `LowSync`. ```APIDOC ## `new LocalStorage(key)` / `new SessionStorage(key)` — Browser Web Storage adapters Synchronous adapters backed by `window.localStorage` and `window.sessionStorage`. JSON data is serialized to a single storage key. Used via `LowSync` since Web Storage is inherently synchronous. ```ts import { LowSync } from 'lowdb' import { LocalStorage, SessionStorage } from 'lowdb/browser' type Cart = { items: { id: string; qty: number }[] } // Persistent across sessions (localStorage) const cartDb = new LowSync(new LocalStorage('shopping-cart'), { items: [] }) cartDb.read() cartDb.update(({ items }) => items.push({ id: 'sku-42', qty: 2 })) // localStorage['shopping-cart'] = '{"items":[{"id":"sku-42","qty":2}]}' // Cleared when tab closes (sessionStorage) type Session = { token: string | null } const sessionDb = new LowSync(new SessionStorage('user-session'), { token: null }) sessionDb.read() sessionDb.update((data) => { data.token = 'eyJhbGci...' }) ``` ``` -------------------------------- ### TextFile / TextFileSync Source: https://context7.com/typicode/lowdb/llms.txt Adapters for reading and writing raw strings. Can be used as a base for custom adapters for non-JSON formats. ```APIDOC ## `new TextFile(filename)` / `new TextFileSync(filename)` — Raw text file adapters Adapters that read and write raw strings. Serve as the underlying primitive for `DataFile` and as a building block for custom adapters targeting non-JSON formats (YAML, TOML, CSV, encrypted blobs). ```ts import { Low } from 'lowdb' import { TextFile } from 'lowdb/node' import YAML from 'yaml' // Build a YAML adapter using TextFile class YAMLFile { #adapter: TextFile constructor(filename: string) { this.#adapter = new TextFile(filename) } async read(): Promise { const text = await this.#adapter.read() return text === null ? null : (YAML.parse(text) as T) } write(obj: T): Promise { return this.#adapter.write(YAML.stringify(obj)) } } type Config = { host: string; port: number } const db = new Low(new YAMLFile('config.yaml'), { host: 'localhost', port: 3000 }) await db.read() await db.update((data) => { data.port = 8080 }) // config.yaml: // host: localhost // port: 8080 ``` ``` -------------------------------- ### Query Data with Array Functions Source: https://github.com/typicode/lowdb/blob/main/README.md Shows how to query data using native JavaScript Array methods directly on `db.data.posts`. No special API is needed for basic querying. ```javascript const { posts } = db.data posts.at(0) // First post posts.filter((post) => post.title.includes('lowdb')) // Filter by title posts.find((post) => post.id === 1) // Find by id posts.toSorted((a, b) => a.views - b.views) // Sort by views ``` -------------------------------- ### Write Data with db.write() Source: https://github.com/typicode/lowdb/blob/main/README.md Use `db.write()` to save the current `db.data` to the adapter. This will update the underlying file or storage. ```javascript db.data = { posts: [] } db.write() // file.json will be { posts: [] } db.data = {} db.write() // file.json will be {} ``` -------------------------------- ### JSONFileSyncPreset Source: https://context7.com/typicode/lowdb/llms.txt Synchronous counterpart to JSONFilePreset. Useful for CLI tools and scripts where async/await is inconvenient. Also switches to MemorySync automatically during tests. ```APIDOC ## `JSONFileSyncPreset(filename, defaultData)` ### Description Synchronous counterpart to `JSONFilePreset`. Useful for CLI tools, scripts, or any context where async/await is inconvenient. Also switches to `MemorySync` automatically during tests. ### Usage ```ts import { JSONFileSyncPreset } from 'lowdb/node' type Data = { messages: string[] } const db = JSONFileSyncPreset('file.json', { messages: [] }) // Append a message passed via CLI argument const message = process.argv[2] ?? 'default message' db.update(({ messages }) => messages.push(message)) ``` ### Example File Content ```json // file.json after running: node cli.js "Hello" { "messages": ["Hello"] } ``` ``` -------------------------------- ### LowSync Source: https://context7.com/typicode/lowdb/llms.txt Synchronous version of Low. Accepts a `SyncAdapter` and provides synchronous `read`, `write`, and `update` methods. Ideal for CLI tools and environments where blocking I/O is acceptable. ```APIDOC ## `new LowSync(adapter, defaultData)` ### Description Synchronous version of `Low`. Accepts a `SyncAdapter`. All methods (`read`, `write`, `update`) are synchronous. Useful for CLI tools, Electron main processes, or any environment where blocking I/O is acceptable. ### Usage ```ts import { LowSync } from 'lowdb' import { JSONFileSync } from 'lowdb/node' type Data = { counter: number } const adapter = new JSONFileSync('counter.json') const db = new LowSync(adapter, { counter: 0 }) db.read() // Increment counter synchronously db.update((data) => { data.counter += 1 }) console.log(db.data.counter) // 1 // Direct mutation + explicit write db.data.counter = 100 db.write() ``` ``` -------------------------------- ### Browser Web Storage Adapters for LowSync Source: https://context7.com/typicode/lowdb/llms.txt Use LocalStorage and SessionStorage for synchronous data persistence across sessions or within a single tab. These adapters serialize JSON data to a single storage key and are used with LowSync. ```typescript import { LowSync } from 'lowdb' import { LocalStorage, SessionStorage } from 'lowdb/browser' type Cart = { items: { id: string; qty: number }[] } // Persistent across sessions (localStorage) const cartDb = new LowSync(new LocalStorage('shopping-cart'), { items: [] }) cartDb.read() cartDb.update(({ items }) => items.push({ id: 'sku-42', qty: 2 })) // localStorage['shopping-cart'] = '{"items":[{"id":"sku-42","qty":2}]}' // Cleared when tab closes (sessionStorage) type Session = { token: string | null } const sessionDb = new LowSync(new SessionStorage('user-session'), { token: null }) sessionDb.read() sessionDb.update((data) => { data.token = 'eyJhbGci...' }) ``` -------------------------------- ### Extend lowdb with Lodash Source: https://github.com/typicode/lowdb/blob/main/README.md Demonstrates how to extend lowdb with Lodash by creating a custom `LowWithLodash` class. This allows using Lodash's chain API for more powerful data manipulation, using `db.chain` instead of `db.data`. ```typescript 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 extends Low { chain: lodash.ExpChain = lodash.chain(this).get('data') } const defaultData: Data = { posts: [], } const adapter = new JSONFile('db.json') const db = new LowWithLodash(adapter, defaultData) await db.read() // Instead of db.data use db.chain to access lodash API const post = db.chain.get('posts').find({ id: 1 }).value() // Important: value() must be called to execute chain ``` -------------------------------- ### DataFile / DataFileSync Source: https://context7.com/typicode/lowdb/llms.txt Generic file adapters that accept custom parse and stringify functions for any text-based serialization format. ```APIDOC ## `new DataFile(filename, { parse, stringify })` / `new DataFileSync(...)` — Custom format adapters Generic file adapters that accept custom `parse` and `stringify` functions, enabling any text-based serialization format. `JSONFile` is built on top of `DataFile`. Supports encryption, compression, or any custom codec. ```ts import { Low } from 'lowdb' import { DataFile } from 'lowdb/node' import YAML from 'yaml' import { encrypt, decrypt } from './crypto.js' // hypothetical crypto module type Secrets = { apiKeys: Record } // YAML adapter const yamlDb = new Low( new DataFile('secrets.yaml', { parse: YAML.parse, stringify: YAML.stringify, }), { apiKeys: {} } ) await yamlDb.read() // Encrypted JSON adapter const encryptedDb = new Low( new DataFile('secrets.enc', { parse: (str) => JSON.parse(decrypt(str)), stringify: (obj) => encrypt(JSON.stringify(obj)), }), { apiKeys: {} } ) await encryptedDb.read() await encryptedDb.update((data) => { data.apiKeys['service-a'] = 'sk-abc123' }) ``` ``` -------------------------------- ### Update and Write Data Source: https://github.com/typicode/lowdb/blob/main/README.md Demonstrates two ways to push data to the posts array and persist changes to the database. Use `db.update` for atomic operations or `db.write` after direct data manipulation. ```javascript const post = { id: 1, title: 'lowdb is awesome', views: 100 } // In two steps db.data.posts.push(post) await db.write() // Or in one await db.update(({ posts }) => posts.push(post)) ``` -------------------------------- ### Sync Database Class Source: https://context7.com/typicode/lowdb/llms.txt LowSync is the synchronous counterpart to Low, suitable for environments where blocking I/O is acceptable. It accepts a SyncAdapter and all methods are synchronous. ```typescript import { LowSync } from 'lowdb' import { JSONFileSync } from 'lowdb/node' type Data = { counter: number } const adapter = new JSONFileSync('counter.json') const db = new LowSync(adapter, { counter: 0 }) db.read() // Increment counter synchronously db.update((data) => { data.counter += 1 }) console.log(db.data.counter) // 1 // Direct mutation + explicit write db.data.counter = 100 db.write() ``` -------------------------------- ### Async and Sync In-Memory Adapters Source: https://context7.com/typicode/lowdb/llms.txt Memory and MemorySync adapters hold data only in RAM, ideal for tests or ephemeral data. The NODE_ENV=test environment variable automatically uses these. ```typescript import { Low, LowSync, Memory, MemorySync } from 'lowdb' // Async in-memory (useful in tests) const db = new Low(new Memory<{ count: number }>(), { count: 0 }) await db.read() await db.update((data) => { data.count += 1 }) console.log(db.data.count) // 1 — data lives only in RAM // Sync in-memory const dbSync = new LowSync(new MemorySync(), []) dbSync.read() dbSync.update((data) => data.push('hello')) console.log(dbSync.data) // ['hello'] ``` ```typescript import { LowSync } from 'lowdb' import { JSONFileSync, MemorySync } from 'lowdb/node' // Pattern: swap adapter based on environment const adapter = process.env.NODE_ENV === 'test' ? new MemorySync<{ logs: string[] }>() : new JSONFileSync<{ logs: string[] }>('logs.json') const logsDb = new LowSync(adapter, { logs: [] }) logsDb.read() ``` -------------------------------- ### Save Metrics with Lazy Updates Source: https://github.com/typicode/lowdb/wiki/Example-of-batching-to-one-write Saves benchmark metrics, creating a new entry if it doesn't exist and pushing values. Changes are not written to disk until .write() is called. ```javascript async function saveMetrics(id, benchmark, value) { let result = results.find({ id, benchmark }); if (!result.value()) { result = results.push({ id, benchmark, values: [] }) .value(); } results.find({ id, benchmark }) .get('values') .push(lodash.round(value, 3)) .value(); } ``` -------------------------------- ### Memory / MemorySync Source: https://context7.com/typicode/lowdb/llms.txt Adapters that hold data in memory only, without persisting to disk. Useful for unit tests or ephemeral data. ```APIDOC ## `new Memory()` / `new MemorySync()` — In-memory adapters Adapters that hold data in memory only — nothing is persisted to disk. `write()` is a no-op in terms of durability. Ideal for unit tests, ephemeral data, or as a starting point for custom adapters. The node presets automatically use these when `NODE_ENV=test`. ```ts import { Low, LowSync, Memory, MemorySync } from 'lowdb' // Async in-memory (useful in tests) const db = new Low(new Memory<{ count: number }>(), { count: 0 }) await db.read() await db.update((data) => { data.count += 1 }) console.log(db.data.count) // 1 — data lives only in RAM // Sync in-memory const dbSync = new LowSync(new MemorySync(), []) dbSync.read() dbSync.update((data) => data.push('hello')) console.log(dbSync.data) // ['hello'] // Pattern: swap adapter based on environment import { JSONFileSync } from 'lowdb/node' const adapter = process.env.NODE_ENV === 'test' ? new MemorySync<{ logs: string[] }>() : new JSONFileSync<{ logs: string[] }>('logs.json') const logsDb = new LowSync(adapter, { logs: [] }) logsDb.read() ``` ``` -------------------------------- ### Custom DataFile Adapters for YAML and Encrypted JSON Source: https://context7.com/typicode/lowdb/llms.txt Utilize DataFile with custom parse and stringify functions for formats like YAML or encrypted JSON. JSONFile is built on top of DataFile. ```typescript import { Low } from 'lowdb' import { DataFile } from 'lowdb/node' import YAML from 'yaml' import { encrypt, decrypt } from './crypto.js' // hypothetical crypto module type Secrets = { apiKeys: Record } // YAML adapter const yamlDb = new Low( new DataFile('secrets.yaml', { parse: YAML.parse, stringify: YAML.stringify, }), { apiKeys: {} } ) await yamlDb.read() // Encrypted JSON adapter const encryptedDb = new Low( new DataFile('secrets.enc', { parse: (str) => JSON.parse(decrypt(str)), stringify: (obj) => encrypt(JSON.stringify(obj)), }), { apiKeys: {} } ) await encryptedDb.read() await encryptedDb.update((data) => { data.apiKeys['service-a'] = 'sk-abc123' }) ``` -------------------------------- ### Write Batched Metrics to File Source: https://github.com/typicode/lowdb/wiki/Example-of-batching-to-one-write Writes all accumulated changes to the Lowdb file. This should be called after all desired mutations have been made using saveMetrics. ```javascript async function writeMetrics() { await results.write(); } ``` -------------------------------- ### Update Data with db.update() Source: https://github.com/typicode/lowdb/blob/main/README.md Use `db.update(fn)` to modify `db.data` by applying a function `fn` and then automatically writing the changes. Ensure your function correctly modifies the data object. ```javascript db.update((data) => { // make changes to data // ... }) // files.json will be updated ``` -------------------------------- ### Set db.data Property Source: https://github.com/typicode/lowdb/blob/main/README.md The `db.data` property holds your database content. It can be any type supported by `JSON.stringify`, such as strings, arrays, or objects. ```javascript db.data = 'string' db.data = [1, 2, 3] db.data = { key: 'value' } ``` -------------------------------- ### Export Functions Source: https://github.com/typicode/lowdb/wiki/Example-of-batching-to-one-write Exports the saveMetrics and writeMetrics functions for use in other modules. ```javascript run(); module.exports = { saveMetrics, writeMetrics }; ``` -------------------------------- ### TypeScript Data Type Checking Source: https://github.com/typicode/lowdb/blob/main/README.md Defines a TypeScript Data type and uses `JSONPreset` with a generic to enforce type safety when modifying the database. This prevents runtime errors by catching type mismatches during development. ```typescript type Data = { messages: string[] } const defaultData: Data = { messages: [] } const db = await JSONPreset('db.json', defaultData) db.data.messages.push('foo') // ✅ Success db.data.messages.push(1) // ❌ TypeScript error ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.