[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-3073":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":22,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":35,"readmeContent":36,"aiSummary":37,"trendingCount":16,"starSnapshotCount":16,"syncStatus":38,"lastSyncTime":39,"discoverSource":40},3073,"lowdb","typicode\u002Flowdb","typicode","Simple and fast JSON database","",null,"JavaScript",22549,967,239,13,0,5,23,1,73.76,"MIT License",false,"main",[25,26,27,28,29,30,31,32,33,34],"database","electron","embeddable","embedded-database","javascript","json","localstorage","lodash","nodejs","storage","2026-06-12 04:00:16","# lowdb [![](http:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdm\u002Flowdb.svg?style=flat)](https:\u002F\u002Fwww.npmjs.org\u002Fpackage\u002Flowdb) [![Node.js CI](https:\u002F\u002Fgithub.com\u002Ftypicode\u002Flowdb\u002Factions\u002Fworkflows\u002Fnode.js.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Ftypicode\u002Flowdb\u002Factions\u002Fworkflows\u002Fnode.js.yml)\n\n> Simple to use type-safe local JSON database 🦉\n> \n> If you know JavaScript, you know how to use lowdb.\n\nRead or create `db.json`\n\n```js\nconst db = await JSONFilePreset('db.json', { posts: [] })\n```\n\nUse plain JavaScript to change data\n\n```js\nconst post = { id: 1, title: 'lowdb is awesome', views: 100 }\n\n\u002F\u002F In two steps\ndb.data.posts.push(post)\nawait db.write()\n\n\u002F\u002F Or in one\nawait db.update(({ posts }) => posts.push(post))\n```\n\n```js\n\u002F\u002F db.json\n{\n  \"posts\": [\n    { \"id\": 1, \"title\": \"lowdb is awesome\", \"views\": 100 }\n  ]\n}\n```\n\nIn the same spirit, query using native `Array` functions:\n\n```js\nconst { posts } = db.data\n\nposts.at(0) \u002F\u002F First post\nposts.filter((post) => post.title.includes('lowdb')) \u002F\u002F Filter by title\nposts.find((post) => post.id === 1) \u002F\u002F Find by id\nposts.toSorted((a, b) => a.views - b.views) \u002F\u002F Sort by views\n```\n\nIt's that simple. `db.data` is just a JavaScript object, no magic.\n\n## Sponsors\n\n\u003Cbr>\n\u003Cbr>\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Fmockend.com\u002F\" target=\"_blank\">\n    \u003Cimg src=\"https:\u002F\u002Fjsonplaceholder.typicode.com\u002Fmockend.svg\" height=\"70px\">\n  \u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Fserpapi.com\u002F?utm_source=typicode\" target=\"_blank\">\n    \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F52b3039d-1e4c-4c68-951c-93f0f1e73611\" height=\"70px\">\n  \u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cbr>\n\u003Cbr>\n\n[Become a sponsor and have your company logo here](https:\u002F\u002Fgithub.com\u002Fsponsors\u002Ftypicode) 👉 [GitHub Sponsors](https:\u002F\u002Fgithub.com\u002Fsponsors\u002Ftypicode)\n\n## Features\n\n- **Lightweight**\n- **Minimalist**\n- **TypeScript**\n- **Plain JavaScript**\n- Safe atomic writes\n- Hackable:\n  - Change storage, file format (JSON, YAML, ...) or add encryption via [adapters](#adapters)\n  - Extend it with lodash, ramda, ... for super powers!\n- Automatically switches to fast in-memory mode during tests\n\n## Install\n\n```sh\nnpm install lowdb\n```\n\n## Usage\n\n_Lowdb is a pure ESM package. If you're having trouble using it in your project, please [read this](https:\u002F\u002Fgist.github.com\u002Fsindresorhus\u002Fa39789f98801d908bbc7ff3ecc99d99c)._\n\n```js\nimport { JSONFilePreset } from 'lowdb\u002Fnode'\n\n\u002F\u002F Read or create db.json\nconst defaultData = { posts: [] }\nconst db = await JSONFilePreset('db.json', defaultData)\n\n\u002F\u002F Update db.json\nawait db.update(({ posts }) => posts.push('hello world'))\n\n\u002F\u002F Alternatively you can call db.write() explicitely later\n\u002F\u002F to write to db.json\ndb.data.posts.push('hello world')\nawait db.write()\n```\n\n```js\n\u002F\u002F db.json\n{\n  \"posts\": [ \"hello world\" ]\n}\n```\n\n### TypeScript\n\nYou can use TypeScript to check your data types.\n\n```ts\ntype Data = {\n  messages: string[]\n}\n\nconst defaultData: Data = { messages: [] }\nconst db = await JSONPreset\u003CData>('db.json', defaultData)\n\ndb.data.messages.push('foo') \u002F\u002F ✅ Success\ndb.data.messages.push(1) \u002F\u002F ❌ TypeScript error\n```\n\n### Lodash\n\nYou can extend lowdb with Lodash (or other libraries). To be able to extend it, we're not using `JSONPreset` here. Instead, we're using lower components.\n\n```ts\nimport { Low } from 'lowdb'\nimport { JSONFile } from 'lowdb\u002Fnode'\nimport lodash from 'lodash'\n\ntype Post = {\n  id: number\n  title: string\n}\n\ntype Data = {\n  posts: Post[]\n}\n\n\u002F\u002F Extend Low class with a new `chain` field\nclass LowWithLodash\u003CT> extends Low\u003CT> {\n  chain: lodash.ExpChain\u003Cthis['data']> = lodash.chain(this).get('data')\n}\n\nconst defaultData: Data = {\n  posts: [],\n}\nconst adapter = new JSONFile\u003CData>('db.json')\n\nconst db = new LowWithLodash(adapter, defaultData)\nawait db.read()\n\n\u002F\u002F Instead of db.data use db.chain to access lodash API\nconst post = db.chain.get('posts').find({ id: 1 }).value() \u002F\u002F Important: value() must be called to execute chain\n```\n\n### CLI, Server, Browser and in tests usage\n\nSee [`src\u002Fexamples\u002F`](src\u002Fexamples) directory.\n\n## API\n\n### Presets\n\nLowdb provides four presets for common cases.\n\n- `JSONFilePreset(filename, defaultData)`\n- `JSONFileSyncPreset(filename, defaultData)`\n- `LocalStoragePreset(name, defaultData)`\n- `SessionStoragePreset(name, defaultData)`\n\nSee [`src\u002Fexamples\u002F`](src\u002Fexamples) directory for usage.\n\nLowdb is extremely flexible, if you need to extend it or modify its behavior, use the classes and adapters below instead of the presets.\n\n### Classes\n\nLowdb has two classes (for asynchronous and synchronous adapters).\n\n#### `new Low(adapter, defaultData)`\n\n```js\nimport { Low } from 'lowdb'\nimport { JSONFile } from 'lowdb\u002Fnode'\n\nconst db = new Low(new JSONFile('file.json'), {})\nawait db.read()\nawait db.write()\n```\n\n#### `new LowSync(adapterSync, defaultData)`\n\n```js\nimport { LowSync } from 'lowdb'\nimport { JSONFileSync } from 'lowdb\u002Fnode'\n\nconst db = new LowSync(new JSONFileSync('file.json'), {})\ndb.read()\ndb.write()\n```\n\n### Methods\n\n#### `db.read()`\n\nCalls `adapter.read()` and sets `db.data`.\n\n**Note:** `JSONFile` and `JSONFileSync` adapters will set `db.data` to `null` if file doesn't exist.\n\n```js\ndb.data \u002F\u002F === null\ndb.read()\ndb.data \u002F\u002F !== null\n```\n\n#### `db.write()`\n\nCalls `adapter.write(db.data)`.\n\n```js\ndb.data = { posts: [] }\ndb.write() \u002F\u002F file.json will be { posts: [] }\ndb.data = {}\ndb.write() \u002F\u002F file.json will be {}\n```\n\n#### `db.update(fn)`\n\nCalls `fn()` then `db.write()`.\n\n```js\ndb.update((data) => {\n  \u002F\u002F make changes to data\n  \u002F\u002F ...\n})\n\u002F\u002F files.json will be updated\n```\n\n### Properties\n\n#### `db.data`\n\nHolds your db content. If you're using the adapters coming with lowdb, it can be any type supported by [`JSON.stringify`](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FJSON\u002Fstringify).\n\nFor example:\n\n```js\ndb.data = 'string'\ndb.data = [1, 2, 3]\ndb.data = { key: 'value' }\n```\n\n## Adapters\n\n### Lowdb adapters\n\n#### `JSONFile` `JSONFileSync`\n\nAdapters for reading and writing JSON files.\n\n```js\nimport { JSONFile, JSONFileSync } from 'lowdb\u002Fnode'\n\nnew Low(new JSONFile(filename), {})\nnew LowSync(new JSONFileSync(filename), {})\n```\n\n#### `Memory` `MemorySync`\n\nIn-memory adapters. Useful for speeding up unit tests. See [`src\u002Fexamples\u002F`](src\u002Fexamples) directory.\n\n```js\nimport { Memory, MemorySync } from 'lowdb'\n\nnew Low(new Memory(), {})\nnew LowSync(new MemorySync(), {})\n```\n\n#### `LocalStorage` `SessionStorage`\n\nSynchronous adapter for `window.localStorage` and `window.sessionStorage`.\n\n```js\nimport { LocalStorage, SessionStorage } from 'lowdb\u002Fbrowser'\nnew LowSync(new LocalStorage(name), {})\nnew LowSync(new SessionStorage(name), {})\n```\n\n### Utility adapters\n\n#### `TextFile` `TextFileSync`\n\nAdapters for reading and writing text. Useful for creating custom adapters.\n\n#### `DataFile` `DataFileSync`\n\nAdapters for easily supporting other data formats or adding behaviors (encrypt, compress...).\n\n```js\nimport { DataFile } from 'lowdb\u002Fnode'\nnew DataFile(filename, {\n  parse: YAML.parse,\n  stringify: YAML.stringify\n})\nnew DataFile(filename, {\n  parse: (data) => { decypt(JSON.parse(data)) },\n  stringify: (str) => { encrypt(JSON.stringify(str)) }\n})\n```\n\n### Third-party adapters\n\nIf you've published an adapter for lowdb, feel free to create a PR to add it here.\n\n### Writing your own adapter\n\nYou may want to create an adapter to write `db.data` to YAML, XML, encrypt data, a remote storage, ...\n\nAn adapter is a simple class that just needs to expose two methods:\n\n```js\nclass AsyncAdapter {\n  read() {\n    \u002F* ... *\u002F\n  } \u002F\u002F should return Promise\u003Cdata>\n  write(data) {\n    \u002F* ... *\u002F\n  } \u002F\u002F should return Promise\u003Cvoid>\n}\n\nclass SyncAdapter {\n  read() {\n    \u002F* ... *\u002F\n  } \u002F\u002F should return data\n  write(data) {\n    \u002F* ... *\u002F\n  } \u002F\u002F should return nothing\n}\n```\n\nFor example, let's say you have some async storage and want to create an adapter for it:\n\n```js\nimport { Low } from 'lowdb'\nimport { api } from '.\u002FAsyncStorage'\n\nclass CustomAsyncAdapter {\n  \u002F\u002F Optional: your adapter can take arguments\n  constructor(args) {\n    \u002F\u002F ...\n  }\n\n  async read() {\n    const data = await api.read()\n    return data\n  }\n\n  async write(data) {\n    await api.write(data)\n  }\n}\n\nconst adapter = new CustomAsyncAdapter()\nconst db = new Low(adapter, {})\n```\n\nSee [`src\u002Fadapters\u002F`](src\u002Fadapters) for more examples.\n\n#### Custom serialization\n\nTo create an adapter for another format than JSON, you can use `TextFile` or `TextFileSync`.\n\nFor example:\n\n```js\nimport { Adapter, Low } from 'lowdb'\nimport { TextFile } from 'lowdb\u002Fnode'\nimport YAML from 'yaml'\n\nclass YAMLFile {\n  constructor(filename) {\n    this.adapter = new TextFile(filename)\n  }\n\n  async read() {\n    const data = await this.adapter.read()\n    if (data === null) {\n      return null\n    } else {\n      return YAML.parse(data)\n    }\n  }\n\n  write(obj) {\n    return this.adapter.write(YAML.stringify(obj))\n  }\n}\n\nconst adapter = new YAMLFile('file.yaml')\nconst db = new Low(adapter, {})\n```\n\n## Limits\n\nLowdb doesn't support Node's cluster module.\n\nIf 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.\n\nDepending 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.\n\nIf you plan to scale, it's highly recommended to use databases like PostgreSQL or MongoDB instead.\n","lowdb 是一个简单且快速的本地 JSON 数据库。它通过使用原生 JavaScript 对象和数组方法来提供类型安全的数据存储与操作，支持 TypeScript 以增强数据类型的检查。其核心功能包括轻量级设计、最小化配置以及支持自定义适配器实现不同的存储格式或加密需求。此外，lowdb 在测试期间自动切换到内存模式以提高性能。此项目适用于需要简单持久化解决方案的小型应用或开发环境，如 Electron 应用程序中的本地存储、小型 Node.js 项目等场景。",2,"2026-06-11 02:52:24","top_language"]