{"id":14563537,"url":"https://github.com/gerold-penz/bun-sqlite-key-value","last_synced_at":"2025-04-12T20:13:27.922Z","repository":{"id":246865846,"uuid":"823781302","full_name":"gerold-penz/bun-sqlite-key-value","owner":"gerold-penz","description":"A super fast key-value store with SQLite that uses bun:sqlite and v8 as a fast JSON replacement.","archived":false,"fork":false,"pushed_at":"2025-01-13T11:55:13.000Z","size":637,"stargazers_count":18,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-12T20:13:22.170Z","etag":null,"topics":["bun","bun-js","cache","data-storage","database","db-storage","key-value","key-value-storage","kv-store","nosql","nosql-database","sqlite","time-to-live","ttl","typescript"],"latest_commit_sha":null,"homepage":"https://gerold-penz.github.io/bun-sqlite-key-value/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gerold-penz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-03T17:46:48.000Z","updated_at":"2025-03-29T19:28:11.000Z","dependencies_parsed_at":"2024-07-17T19:08:14.035Z","dependency_job_id":"faadc65d-86e5-4b60-99c5-71119d50fb36","html_url":"https://github.com/gerold-penz/bun-sqlite-key-value","commit_stats":null,"previous_names":["gerold-penz/bun-sqlite-key-value"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerold-penz%2Fbun-sqlite-key-value","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerold-penz%2Fbun-sqlite-key-value/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerold-penz%2Fbun-sqlite-key-value/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerold-penz%2Fbun-sqlite-key-value/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gerold-penz","download_url":"https://codeload.github.com/gerold-penz/bun-sqlite-key-value/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248625517,"owners_count":21135514,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bun","bun-js","cache","data-storage","database","db-storage","key-value","key-value-storage","kv-store","nosql","nosql-database","sqlite","time-to-live","ttl","typescript"],"created_at":"2024-09-07T02:02:15.254Z","updated_at":"2025-04-12T20:13:27.901Z","avatar_url":"https://github.com/gerold-penz.png","language":"TypeScript","funding_links":[],"categories":["typescript"],"sub_categories":[],"readme":"# Bun SQLite Key Value\n\nA super fast key-value store with SQLite that uses **bun:sqlite** \nand v8 as a fast JSON replacement.\n\n[![license](https://img.shields.io/badge/license-MIT-brightgreen)](LICENSE)\n[![npm version](https://img.shields.io/npm/v/bun-sqlite-key-value.svg)](https://www.npmjs.com/package/bun-sqlite-key-value)\n[![npm downloads](https://img.shields.io/npm/dw/bun-sqlite-key-value)](https://www.npmjs.com/package/bun-sqlite-key-value)\n[![bun:sqlite](https://img.shields.io/badge/bun-%3Asqlite-044a64?style=flat\u0026logo=Bun\u0026logoColor=f6dece\u0026link=https%3A%2F%2Fbun.sh%2Fdocs%2Fapi%2Fsqlite\n)](https://bun.sh/docs/api/sqlite)\n\n[Bun's](https://bun.sh/) lightning-fast \n[SQLite implementation](https://bun.sh/docs/api/sqlite) makes Bun-SQLite-Key-Value \nperfect for a fast and reliable storage and cache solution with TTL support.\n*You need [Bun](https://bun.sh/) to be able to use this package.*\n\nThe ideas for the implementation come from \n[bun-sqlite-cache](https://github.com/notskamr/bun-sqlite-cache) and \n[bun-kv](https://github.com/kirill-dev-pro/bun-kv). Thank you very much!\n\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Usage](#usage)\n- Database Usage\n  - [Open Database](#open-database)\n  - [Close Database](#close-database)\n- Write and Read Values\n  - [`set()`](#write-value)\n  - [`get()`](#read-value)\n  - [`getSet()`](#read-and-write-value-in-one-step)\n  - [`getValues()`](#read-multiple-values)\n  - `getValuesAsSet()` --\u003e Set with values\n- Write and Read Items\n  - [`setItems()`](#write-multiple-items)\n  - [`getItem()`](#read-item)\n  - [`getItems()`](#read-multiple-items)\n  - `getItemsAsObject()` --\u003e Object with items\n  - `getItemsAsMap()` --\u003e Map with items\n  - [Read and Write Binary Files (Images)](#read-and-write-binary-files-images)\n- Keys\n  - [`has()`](#has-key)\n  - [`getKeys()`](#read-multiple-keys)\n  - [`rename()`](#rename-key)\n- Delete Items\n  - [`delete()`](#delete-items)\n  - [`deleteExpired()`](#delete-expired-items)\n  - [`deleteOldExpiringItems()`](#delete-old-expiring-items)\n- Count Items\n  - [`getCount()`](#count-all-items)\n  - [`getCountValid()`](#count-valid-items)\n- Expiration/TTL (Time To Live)\n  - [Cache Values with TTL](#cache-values-with-ttl)\n  - [`setTtl()`](#set-ttl)\n  - [`getTtl()`](#get-ttl)\n- Random\n  - [`getRandomValue()`](#random-value)\n  - [`getRandomItem()`](#random-item)\n  - [`getRandomKey()`](#random-key)\n- Math\n  - [`incr()`](#increment)\n  - [`decr()`](#decrement)\n- String\n  - [`append()`](#append)\n- Hash (Map Object)\n  - [`hSet()`](#hash-map-object---write-value)\n  - [`hGet()`](#hash-map-object---read-value)\n  - [`hmSet()`](#hash-map-object---write-multiple-values)\n  - [`hmGet()`](#hash-map-object---read-multiple-values)\n  - [`hHasField()`](#hash-map-object---has-field)\n  - [`hGetCount()`](#hash-map-object---count-fields)\n  - [`hGetFields()`](#hash-map-object---get-all-field-names)\n  - [`hGetValues()`](#hash-map-object---get-all-values)\n  - [`hDelete()`](#hash-map-object---delete-field)\n  - `hIncr()` --\u003e Increments the value of a field.\n  - `hDecr()` --\u003e Decrements the value of a field.\n- List (Array Object)\n  - `lPush()` --\u003e Insert elements at the begin of the list.\n  - `rPush()` --\u003e Insert elements at the end of the list.\n  - `lPop()` --\u003e Returns elements at the begin of the list and removes them.\n  - `rPop()` --\u003e Returns elements at the end of the list and removes them.\n  - `lIndex()` --\u003e Returns the element at the specified index of the list.\n  - `lLen()` --\u003e Returns the length of the list.\n  - `lSet()` --\u003e Updates the element at the specified index of the list.\n- Tags (Labels)\n  - `addTag()` --\u003e Adds a tag to an item.\n  - `deleteTag()` --\u003e Deletes a tag of an item.\n  - `deleteTags()` --\u003e Deletes multiple tags or all tags of an item.\n  - `deleteTaggedItems()` --\u003e Deletes tagged items.\n  - `getTaggedKeys()` --\u003e Returns tagged keys.\n  - `getTaggedValues()` --\u003e Returns tagged values.\n  - `getTaggedItems()` --\u003e Returns tagged items.\n- Extended database topics\n  - [Multiple Databases](#multiple-databases)\n  - [Database Transactions](#database-transactions)\n  - [SQLite as base for a key value storage](#sqlite-as-base-for-a-key-value-storage)\n\n\n## Installation\n\n```bash\nbun add bun-sqlite-key-value\n```\n\n## Usage\n\nUsing this key value store is dead simple:\ncreate a new BunSqliteKeyValue instance and you're set.\nAnd if you want to save the data permanently, enter the path to the database.\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\n// Use regular methods to write and read values.\nstore.set(\"myKey\", [1, 2, 3, 4])\nstore.get(\"myKey\") // --\u003e [ 1, 2, 3, 4 ]\n\n// Or use the `data` object for simple write and read access.\nstore.data.myKey = \"Hello world!\"\nstore.data.myKey // --\u003e \"Hello World\"\n```\n\n## Open Database\n\n```typescript\nconst store = new BunSqliteKeyValue(filename?, options?)\n```\n\nOpens and creates the SQLite database either in memory or on the file system.\n\n### filename (optional)\n\nThe full path of the SQLite database to open.\nPass an empty string (`\"\"`) or `\":memory:\"` or `undefined` for an in-memory database.\n\n### options (optional)\n\n`readonly?: boolean`: \n  Open the database as read-only (default: false).\n\n`create?: boolean`:\n  Allow creating a new database (default: true).\n  If the database folder does not exist, it will be created.\n\n`readwrite?: boolean`: \n  Open the database as read-write (default: true).\n\n`ttlMs?: boolean`:\n  Default time span in milliseconds before an item \n  written to the DB becomes invalid and is marked for deletion.\n\n`maxExpiringItemsInDb?: number`:\n  Default value that specifies the maximum number of \n  expiring items that may be in the database.\n  Is used by the `deleteOldExpiringItems()` method as default value.\n\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\n// In-memory\nconst store1 = new BunSqliteKeyValue()\n// In-memory with 30 seconds default expiration timeout\nconst store2 = new BunSqliteKeyValue(\":memory:\", {ttlMs: 30000})\n// Store items in file system\nconst store3 = new BunSqliteKeyValue(\"./store3.sqlite\")\n```\n\n\n## Close Database\n\n```typescript\nclose()\n```\nCloses database and removes *.sqlite-shm* and *.sqlite-wal* files.\n\n\n## Write Value\n\n```typescript\nset(key: string | undefined, value: any, ttlMs?: number): Key\n\ndata.\u003ckey\u003e = \u003cvalue\u003e\ndata[\u003ckey\u003e] = \u003cvalue\u003e\n```\n\nWrites a value into the database and returns the key.\n\n### key\n\nThe `key` can be a string or `undefined`.\nIf the `key` is `undefined`, a UUID is used instead.\n\n### value\n\nThe value can be any object that can be serialized with\n[v8](https://github.com/nodejs/node/blob/main/doc/api/v8.md#serialization-api).\nThis means that not only simple data types (string, number) are possible,\nbut also more complex types such as sets or maps.\nYou can find a list of the\n[supported data types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#supported_types) here. \n\n### ttlMs (optional)\n\n\"Time to live\" in milliseconds. After this time, \nthe item becomes invalid and is deleted from the database \nthe next time it is accessed or when the application is started.\nSet the value to 0 if you want to explicitly deactivate the process.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\n// Stays in database\nstore.set(\"myKey1\", \"my-value\")\n\nstore.data.myKey2 = \"my-value\"\nstore.data[\"myKey3\"] = \"my-value\"\n\n// Becomes invalid after 30 seconds\nstore.set(\"myKey6\", \"item-with-ttl\", 30000)\n```\n\n\n## Read Value\n\n```typescript\nget(key: string): any\n\ndata.\u003ckey\u003e: any\ndata[\u003ckey\u003e]: any\n```\n\nReads a value from the database.\n\n### key\n\nThe key must be a string.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.set(\"myKey\", \"my-value\")\n\nstore.get(\"myKey\") // --\u003e \"my-value\"\n\nstore.data.myKey // --\u003e \"my-value\"\nstore.data[\"myKey\"] // --\u003e \"my-value\"\n```\n\n\n## Read and Write Value (in one step)\n\n```typescript\ngetSet(key: string, value: any, ttlMs?: number)\n```\n\nAtomically sets key to value and returns the old value stored at key.\nInspired by: [https://docs.keydb.dev/docs/commands/#getset](https://docs.keydb.dev/docs/commands/#getset)\n\n### key\n\nThe key must be a string.\n\n### value\n\nThe value can be any object that can be serialized with\n[v8](https://github.com/nodejs/node/blob/main/doc/api/v8.md#serialization-api).\nThis means that not only simple data types (string, number) are possible,\nbut also more complex types such as sets or maps.\nYou can find a list of the\n[supported data types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#supported_types) here. \n\n### ttlMs (optional)\n\n\"Time to live\" in milliseconds. After this time, \nthe item becomes invalid and is deleted from the database \nthe next time it is accessed or when the application is started.\nSet the value to 0 if you want to explicitly deactivate the process.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.set(\"key-1\", \"string-value-1\")\nstore.getSet(\"key-1\", \"string-value-2\")) // --\u003e \"string-value-1\"\nstore.get(\"key-1\") // --\u003e \"string-value-2\"\n```\n\n\n## Read Multiple Values\n\n```typescript\ngetValues(startsWithOrKeys?: string | string[]): any[]\n\n\u003cstore\u003e.values\n```\n\nReads the data from the database and returns an array with the values.\n\n### startsWithOrKeys\n\n`undefined`: Returns an array with all values.\n\n`string`: Returns an array with all values whose keys begin with the passed string.\n  If you plan the names of the keys well, more complex data can be stored.\n  It is advisable to divide keys into ranges using separators.\n  For example `\"language:de\"`, `\"language:en\"`, `\"language:it\"`.\n  A search for `\"language:\"` would return all languages.\n\n`string[]`: Array with keys. The returned array is exactly \n  the same size as the passed array.\n  Items that are not found are returned as `undefined`.\n  Only exact matches with the keys are returned.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.set(\"language:de\", \"German\")\nstore.set(\"language:en\", \"English\")\nstore.set(\"language:it\", \"Italian\")\n\nstore.getValues() // --\u003e [ \"German\", \"English\", \"Italian\" ]\nstore.getValues(\"language:\") // --\u003e [ \"German\", \"English\", \"Italian\" ]\n\nstore.values // --\u003e [ \"German\", \"English\", \"Italian\" ]\n```\n\n\n## Write Multiple Items\n\n```typescript\nsetItems(items: {key: string, value: T, ttlMs?: number}[])\n```\n\nAdds a large number of items to the database and takes only\na small fraction of the time that `set()` would take individually.\n\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\n// Add many records\nstore.setItems([\n    {key: \"a:1\", value: \"test-value-1\"},\n    {key: \"a:2\", value: \"test-value-2\"},\n])\n```\n\n\n## Read Item\n\nReads the key and the value from the database.\n\n```typescript\ngetItem(key: string): {key: string, value: any}\n```\n\n### key\n\nThe key must be a string.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\nstore.set(\"my-key\", \"my-value\")\n\nconst item = store.getItem(\"my-key\")\nconsole.log(item)  // --\u003e {key: \"my-key\", value: \"my-value\"}\n```\n\n\n## Read Multiple Items\n\n```typescript\ngetItems(startsWithOrKeys?: string | string[]): {key: string, value: any}[]\n\n\u003cstore\u003e.items\n```\nReads the data from the database and returns items in an array as key-value pairs.\n\n### startsWithOrKeys\n\n`undefined`: Returns all items (key, value) in an array.\n\n`string`: Returns all items (key, value) in an array whose keys begin with \n  the passed string.\n  If you plan the names of the keys well, more complex data can be stored.\n  It is advisable to divide keys into ranges using separators.\n  For example `\"language:de\"`, `\"language:en\"`, `\"language:it\"`.\n  A search for `\"language:\"` would return all languages.\n\n`string[]`: Array with keys. The returned array is exactly \n  the same size as the passed array.\n  Items that are not found are returned as `undefined`.\n  Only exact matches with the keys are returned.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.set(\"language:de\", \"German\")\nstore.set(\"language:en\", \"English\")\nstore.set(\"language:it\", \"Italian\")\n\nstore.getItems(\"language:\") // --\u003e [\n//     {key: \"language:de\", value: \"German\"},\n//     {key: \"language:en\", value: \"English\"},\n//     {key: \"language:it\", value: \"Italian\"}\n// ]\n\nstore.items // --\u003e [\n//     {key: \"language:de\", value: \"German\"},\n//     {key: \"language:en\", value: \"English\"},\n//     {key: \"language:it\", value: \"Italian\"}\n// ]\n\n```\n\n\n## Read and Write Binary Files (Images)\n\nSQLite has no problem with images and other binaries.\nThe maximum size of a binary file is 2 GB.\n\n### Example (async)\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\n// Read file from filesystem\nconst sourceFile = Bun.file(\"\u003cSource File Path\u003e\")\n\n// Write ArrayBuffer into database (async !!!)\nstore.set(\"my-image\", await sourceFile.arrayBuffer())\n\n// Read ArrayBuffer from database\nconst targetArrayBuffer = store.get(\"my-image\")\n\n// Write target file to filesystem (async !!!)\nawait Bun.write(Bun.file(\"\u003cTarget File Path\u003e\"), targetArrayBuffer)\n```\n\n### Example (sync)\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\nimport { readFileSync, writeFileSync } from \"node:fs\"\n\nconst store = new BunSqliteKeyValue()\n\n// Read content from filesystem\nconst sourceContent = readFileSync(\"\u003cSource File Path\u003e\")\n\n// Write Buffer into database\nstore.set(\"my-image\", sourceContent)\n\n// Read Buffer from database\nconst targetBuffer = store.get(\"my-image\")\n\n// Write target file to filesystem\nwriteFileSync(\"\u003cTarget File Path\u003e\", targetBuffer)\n```\n\n\n## Has (key)\n\n```typescript\nhas(key: string): boolean\n\nexists(key: string) // --\u003e alias for has()\n\n\u003ckey\u003e in \u003cstore\u003e.data\n```\n\nChecks if key exists. Returns `false` if the item is expired.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.has(\"my-key\") // --\u003e false\nconsole.log(\"my-key\" in store.data) // --\u003e false \n```\n\n\n## Read Multiple Keys\n\n```typescript\ngetKeys(startsWithOrKeys?: string | string[]): string[]\n\n\u003cstore\u003e.keys // --\u003e all keys\n```\n\nReads the keys from the database and returns an array.\n\n### startsWithOrKeys\n\n`undefined`: Returns all keys in an array.\n\n`string`: Returns an array with the keys that begin with the passed string.\n  If you plan the names of the keys well, more complex data can be stored.\n  It is advisable to divide keys into ranges using separators.\n  For example `\"language:de\"`, `\"language:en\"`, `\"language:it\"`.\n  A search for `\"language:\"` would return all languages.\n\n`string[]`: Array with keys. \n  Only exact matches with the keys are returned.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.set(\"language:de\", \"German\")\nstore.set(\"language:en\", \"English\")\nstore.set(\"language:es\", \"Esperanto\")\n\nstore.getKeys() // --\u003e [\"language:de\", \"language:en\", \"language:es\"]\n\nstore.keys // --\u003e [\"language:de\", \"language:en\", \"language:es\"]\n\nstore.getKeys(\"language:e\") // --\u003e [\"language:en\", \"language:es\"]\n\nstore.getKeys([\"language:de\", \"language:fr\"]) // --\u003e [\"language:de\"]\n\n```\n\n\n## Rename Key\n\n```typescript\nrename(oldKey: string, newKey: string): boolean\n```\n\nRenames `oldKey` to `newKey`.\nIt returns `false` when `oldKey` does not exist.\nIf `newKey` already exists it is deleted first.\nInspired by: [https://docs.keydb.dev/docs/commands/#rename](https://docs.keydb.dev/docs/commands/#rename)\n\n\n## Delete Items\n\n```typescript\ndelete(keyOrKeys?: string | string[])\n\nclear() // --\u003e delete all items\n\ndelete \u003cstore\u003e.data.\u003ckey\u003e\n```\n\nDeletes all items if no parameter was passed.\n\n`key: string`: Deletes the item whose key was passed as a string.\n\n`keys: string[]`: Deletes the items whose keys were passed in an array.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\n// Delete all items\nstore.delete()\nstore.clear()\n\n// Delete one item\nstore.delete(\"myKey\")\ndelete store.data.myKey\n\n// Delete multiple items\nstore.delete([\"key1\", \"key2\"])\n```\n\n\n## Delete Expired Items\n\n```typescript\ndeleteExpired()\n```\n\nDeletes all expired items. \nThese are items whose TTL (Time to live) has expired.\nThese items are not deleted continuously, \nbut only when they are accessed directly or when the database is opened.\nIf you want to delete the expired items in between, \nyou can do this with `deleteExpired()`.\n\n\n## Delete Old Expiring Items\n\n```typescript\ndeleteOldExpiringItems(maxExpiringItemsInDb?: number)\n```\n\nIf there are more expiring items in the database than `maxExpiringItemsInDb`,\nthe oldest items are deleted until there are only `maxExpiringItemsInDb` items with\nan expiration date in the database.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.set(\"static:1\", \"my-value\")\nstore.set(\"static:2\", \"my-value\")\nstore.set(\"dynamic:1\", \"my-value\", 4000)\nstore.set(\"dynamic:2\", \"my-value\", 5000)\nstore.set(\"dynamic:3\", \"my-value\", 6000)\n\nstore.deleteOldExpiringItems(2)\nconsole.log(store.getKeys(\"dynamic:\"))\n// --\u003e [ \"dynamic:2\", \"dynamic:3\" ]\n```\n\n\n## Count All Items\n\n```typescript\ngetCount(): number\n\ncount() // --\u003e alias for getCount()\nlength // --\u003e getter method for `getCount()`\n```\n\nReturns the number of all items, including those that have already expired.\nThe fact that possibly expired items are also counted is for reasons of speed.\nUse `getCountValid()` if you want to get the number of items that have not yet expired.\nIf you do not use `ttlMs` (time to live), `getCount()` is faster than `getCountValid()`. \n\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.set(\"my-key1\", \"my-value1\")\nstore.set(\"my-key2\", \"my-value2\")\n\nstore.getCount() // --\u003e 2\nstore.length // --\u003e 2\n```\n\n\n## Count Valid Items\n\n```typescript\ngetCountValid(deleteExpired?: boolean): number\n```\n\nReturns the number of valid (non-expired) items.\nCan also delete the expired items.\n\n### deleteExpired\n\nIf `true` is passed, the expired items are deleted first \nbefore the items are counted.\n\nIf the parameter is not specified or `false` is passed, \nthen only the items that have no expiration date or \nwhose expiration date is in the future are counted.\n\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.set(\"my-key1\", \"my-value1\")\nstore.set(\"my-key2\", \"my-value2\", 100)\n\nstore.getCountValid() // --\u003e 2\n\nawait Bun.sleep(500)\nstore.getCountValid() // --\u003e 1\n```\n\n\n## Cache Values with TTL\n\nYou can specify a caching period when you open the database. \nThis period in milliseconds is then added with each write. \nIf you read the value within this period, the value is returned. \nIf the value is read after this period, `undefined` is returned.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue(\":memory:\", {ttlMs: 1000})\n\nconst KEY = \"cache-key\"\nstore.set(KEY, 12345)\n\nawait Bun.sleep(500)\nconsole.log(store.get(KEY)) // --\u003e 12345\n\nawait Bun.sleep(1000)\nconsole.log(store.get(KEY)) // --\u003e undefined\n```\n\n\n## Set TTL\n\n```typescript\nsetTtl(key: string, ttlMs?: number): boolean\n```\n\nRenews or deletes the TTL of the database row.\nReturns `true` if the `key` exists.\n\n### key\n\nThe key must be a string.\n\n### ttlMs (optional)\n\n\"Time to live\" in milliseconds. After this time, \nthe item becomes invalid and is deleted from the database \nthe next time it is accessed or when the application is started.\nUses the global `ttlMs` as default value.\nSet the value to 0 if you want to delete the TTL.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.set(\"my-key\", \"my-value\", 10000)\n\n// Update TTL\nstore.setTtl(\"my-key\", 10000) // --\u003e true\n\n// Delete TTL\nstore.setTtl(\"my-key\", 0) // --\u003e true\n```\n\n\n## Get TTL\n\n```typescript\ngetTtl(key: string): number | undefined\n```\n\nReturns how long the data record is still valid (in milliseconds).\nReturns `undefined` if the `key` does not exist or no expiration date has been set.\n\nInspired by: [https://docs.keydb.dev/docs/commands/#ttl](https://docs.keydb.dev/docs/commands/#ttl)\n\n### key\n\nThe key must be a string.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.set(\"my-key\", \"my-value\", 20000)\nawait Bun.sleep(1)\nstore.getTtl(\"my-key\") // --\u003e 19999\n```\n\n\n## Random Value\n\n```typescript\ngetRandomValue(): any // --\u003e random value\n\nrandomValue() // --\u003e alias for getRandomValue()\n```\n\nReturns a random value or `undefined` if no valid item was found.\nInspired by: [https://docs.keydb.dev/docs/commands/#randomkey](https://docs.keydb.dev/docs/commands/#randomkey)\n\n\n## Random Item\n\n```typescript\ngetRandomItem() // --\u003e random item\n\nrandomItem() // --\u003e alias for getRandomItem()\n```\n\nReturns a random item or `undefined` if no valid item was found.\nInspired by: [https://docs.keydb.dev/docs/commands/#randomkey](https://docs.keydb.dev/docs/commands/#randomkey)\n\n\n## Random Key\n\n```typescript\ngetRandomKey() // --\u003e random key\n\nrandomKey() // --\u003e alias for getRandomKey()\n```\n\nReturns a random key or `undefined` if no valid item was found.\nInspired by: [https://docs.keydb.dev/docs/commands/#randomkey](https://docs.keydb.dev/docs/commands/#randomkey)\n\n\n## Increment\n\n```typescript\nincr(key: string, incrBy: number = 1, ttlMs?: number): number\n```\n\nIncrements the saved number by `incrBy` (default = 1), \nsaves the new number and returns it.\nIf the key does not yet exist in the database, \nthe value is set to 0 before being incremented by `incrBy`.\nIf a string is stored in the database that can be converted into a number, \nthis is converted first.\nIf the stored value cannot be converted into a number, `NaN` is returned.\n\n### key\n\nThe key must be a string.\n\n### incrBy\n\nThe stored number is increased by this value.\n\n### ttlMs (optional)\n\n\"Time to live\" in milliseconds. After this time, \nthe item becomes invalid and is deleted from the database \nthe next time it is accessed or when the application is started.\nSet the value to 0 if you want to explicitly deactivate the process.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.incr(\"my-key\") // --\u003e 1\nstore.incr(\"my-key\") // --\u003e 2\n```\n\n\n## Decrement\n\n```typescript\ndecr(key: string, decrBy: number = 1, ttlMs?: number): number\n```\n\nDecrements the saved number by `decrBy` (default = 1), \nsaves the new number and returns it.\nIf the key does not yet exist in the database, \nthe value is set to 0 before being decremented by `decrBy`.\nIf a string is stored in the database that can be converted into a number, \nthis is converted first.\nIf the stored value cannot be converted into a number, `NaN` is returned.\n\n### key\n\nThe key must be a string.\n\n### incrBy\n\nThe stored number is decreased by this value.\n\n### ttlMs (optional)\n\n\"Time to live\" in milliseconds. After this time, \nthe item becomes invalid and is deleted from the database \nthe next time it is accessed or when the application is started.\nSet the value to 0 if you want to explicitly deactivate the process.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.set(\"my-key\", 10)\nstore.decr(\"my-key\") // --\u003e 9\nstore.decr(\"my-key\") // --\u003e 8\n```\n\n\n## Append\n\n```typescript\nappend(key: string, value: string, ttlMs?: number): number\n```\n\nIf key already exists, this command appends the value at the end of the string.\nIf key does not exist it is created and set as an empty string,\nso `append()` will be similar to `set()` in this special case.\nInspired by: [https://docs.keydb.dev/docs/commands/#append](https://docs.keydb.dev/docs/commands/#append)\n\nReturns the length of the string after the append operation.\n\n### key\n\nThe key must be a string.\n\n### value\n\nThe string that is appended to the existing string.\n\n### ttlMs (optional)\n\n\"Time to live\" in milliseconds. After this time, \nthe item becomes invalid and is deleted from the database \nthe next time it is accessed or when the application is started.\nSet the value to 0 if you want to explicitly deactivate the process.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.append(\"my-key\", \"Hello!\") // --\u003e 6\nstore.append(\"my-key\", \"World!\") // --\u003e 12 \nstore.get(\"my-key\") // --\u003e \"Hello!World!\"\n```\n\n\n## Hash (Map Object) - Write Value\n\n```typescript\nhSet(key: string, field: string, value: any, ttlMs?: number)\n```\n\nFirst the \n[JavaScript Map Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) \nis read from the database.\nIf the data record does not yet exist, a new \"Map Object\" is created.\nThen the entry marked with `field` is added to the \"Map Object\" or overwritten. \nFinally, the modified \"Map Object\" is written back to the database.\n\nInspired by: [https://docs.keydb.dev/docs/commands/#hset](https://docs.keydb.dev/docs/commands/#hset)\n\n\u003e Do not use the hash functions with several very large amounts (megabytes) of data or blobs.\n\u003e This is because the entire data record with all fields is always read and written.\n\u003e It is better to use `setValues()` and `getValues()` for large amounts of data.\n\n### key\n\nThe key must be a string.\n\n### field\n\nThe field name must be a string.\n\n### value\n\nThe value can be any object that can be serialized with\n[v8](https://github.com/nodejs/node/blob/main/doc/api/v8.md#serialization-api).\nThis means that not only simple data types (string, number) are possible,\nbut also more complex types such as sets or maps.\nYou can find a list of the\n[supported data types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#supported_types) here. \n\n### ttlMs (optional)\n\n\"Time to live\" in milliseconds (for the database line, marked with `key`).\nAfter this time, the item becomes invalid and is deleted from the database \nthe next time it is accessed or when the application is started.\nSet the value to 0 if you want to explicitly deactivate the process.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.hSet(\"key-1\", \"field-1\", \"value-1\")\nstore.hSet(\"key-1\", \"field-2\", \"value-2\")\n\nstore.get(\"key-1\") // --\u003e Map(2) {\n  \"name-1\": \"value-1\",\n  \"name-2\": \"value-2\",\n}\n```\n\n\n## Hash (Map Object) - Read Value\n\n```typescript\nhGet(key: string, field: string)\n```\n\nFirst the \n[JavaScript Map Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) \nis read from the database.\nIf the data record (marked with `key`) does not exist, `undefined` is returned.\nIf the field (marked with `field`) does not exist in the \"Map Object\", `undefined` is returned.\n\n\u003e Do not use the hash functions with several very large amounts (megabytes) of data or blobs.\n\u003e This is because the entire data record with all fields is always read and written.\n\u003e It is better to use `setValues()` and `getValues()` for large amounts of data.\n\nInspired by: [https://docs.keydb.dev/docs/commands/#hget](https://docs.keydb.dev/docs/commands/#hget)\n\n### key\n\nThe key must be a string.\n\n### field\n\nThe field name must be a string.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.hSet(\"key-1\", \"field-1\", \"value-1\")\n\nstore.hGet(\"key-1\", \"field-1\") // --\u003e \"value-1\"\nstore.hGet(\"key-1\", \"field-2\") // --\u003e undefined\n```\n\n\n## Hash (Map Object) - Write Multiple Values\n\n```typescript\nhmSet(key: string, fields: {[field: string]: T}, ttlMs?: number)\n```\n\nLike `hSet()`, with the difference that several fields \nare written to the database in one go.\n\n\u003e Do not use the hash functions with several very large amounts (megabytes) of data or blobs.\n\u003e This is because the entire data record with all fields is always read and written.\n\u003e It is better to use `setValues()` and `getValues()` for large amounts of data.\n\nInspired by: [https://docs.keydb.dev/docs/commands/#hmset](https://docs.keydb.dev/docs/commands/#hmset)\n\n### key\n\nThe key must be a string.\n\n### fields\n\nObject with field names (keys) and values.\n\n### ttlMs (optional)\n\n\"Time to live\" in milliseconds (for the database line, marked with `key`).\nAfter this time, the item becomes invalid and is deleted from the database \nthe next time it is accessed or when the application is started.\nSet the value to 0 if you want to explicitly deactivate the process.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.hmSet(\"my-key\", {\n    \"field-1\": \"value-1\",\n    \"field-2\": \"value-2\",\n    \"field-3\": \"value-3\"\n})\n```\n\n\n## Hash (Map Object) - Read Multiple Values\n\n```typescript\nhmGet(key: string, fields: fields?: string[])\n```\n\nLike `hGet()`, with the difference that several fields are read in one go.\n\n\u003e Do not use the hash functions with several very large amounts (megabytes) of data or blobs.\n\u003e This is because the entire data record with all fields is always read and written.\n\u003e It is better to use `setValues()` and `getValues()` for large amounts of data.\n\nInspired by: [https://docs.keydb.dev/docs/commands/#hmget](https://docs.keydb.dev/docs/commands/#hmget)\n\n### key\n\nThe key must be a string.\n\n### fields\n\nArray with field names.\nIf the parameter is not specified, all fields are returned.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.hmSet(\"my-key\", {\n    \"field-1\": \"value-1\",\n    \"field-2\": \"value-2\"\n})\n\nstore.hmGet(KEY_1, [\"field-1\", \"field-100\"]) // --\u003e {\n//   \"field-1\": \"value-1\",\n//   \"field-100\": undefined,\n// }\n```\n\n\n## Hash (Map Object) - Has Field\n\n```typescript\nhHasField(key: string, field: string)\n```\n\nReturns if `field` is an existing field in the hash stored at `key`.\n\n\u003e Do not use the hash functions with several very large amounts (megabytes) of data or blobs.\n\u003e This is because the entire data record with all fields is always read and written.\n\u003e It is better to use `setValues()` and `getValues()` for large amounts of data.\n\nInspired by: [https://docs.keydb.dev/docs/commands/#hexists](https://docs.keydb.dev/docs/commands/#hexists)\n\n### key\n\nThe key must be a string.\n\n### field\n\nThe field name must be a string.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.hSet(\"key-1\", \"field-1\", \"value-1\")\n\nstore.hHasField(\"key-1\", \"field-1\") // --\u003e true\nstore.hHasField(\"key-1\", \"field-1\") // --\u003e undefined\n```\n\n\n## Hash (Map Object) - Count Fields\n\n```typescript\nhGetCount(key: string)\n```\n\nReturns the number of fields contained in the hash stored at `key`.\n\n\u003e Do not use the hash functions with several very large amounts (megabytes) of data or blobs.\n\u003e This is because the entire data record with all fields is always read and written.\n\u003e It is better to use `setValues()` and `getValues()` for large amounts of data.\n\nInspired by: [https://docs.keydb.dev/docs/commands/#hlen](https://docs.keydb.dev/docs/commands/#hlen)\n\n### key\n\nThe key must be a string.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.hGetCount(\"key-1\") // --\u003e undefined\nstore.hSet(\"key-1\", \"field-1\", \"value-1\")\nstore.hGetCount(\"key-1\") // --\u003e 1\n```\n\n\n## Hash (Map Object) - Get All Field Names\n\n```typescript\nhGetFields(key: string)\n```\n\nReturns the field names contained in the hash stored at `key`.\nUse `hmGet()` to read field names and values.\n\n\u003e Do not use the hash functions with several very large amounts (megabytes) of data or blobs.\n\u003e This is because the entire data record with all fields is always read and written.\n\u003e It is better to use `setValues()` and `getValues()` for large amounts of data.\n\nInspired by: [https://docs.keydb.dev/docs/commands/#hkeys](https://docs.keydb.dev/docs/commands/#hkeys)\n\n### key\n\nThe key must be a string.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.hmSet(\"key-1\", {\n    \"field-1\": \"value-1\",\n    \"field-2\": \"value-2\"\n})\nstore.hGetFields(\"key-1\") // --\u003e [\"field-1\", \"field-2\"]\n```\n\n\n## Hash (Map Object) - Get All Values\n\n```typescript\nhGetValues(key: string)\n```\n\nReturns the values contained in the hash stored at `key`.\nUse `hmGet()` to read field names and values.\n\n\u003e Do not use the hash functions with several very large amounts (megabytes) of data or blobs.\n\u003e This is because the entire data record with all fields is always read and written.\n\u003e It is better to use `setValues()` and `getValues()` for large amounts of data.\n\nInspired by: [https://docs.keydb.dev/docs/commands/#hvals](https://docs.keydb.dev/docs/commands/#hvals)\n\n### key\n\nThe key must be a string.\n\n### Example\n\n```TypeScript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.hmSet(\"key-1\", {\n    \"field-1\": \"value-1\",\n    \"field-2\": \"value-2\"\n})\nstore.hGetValues(\"key-1\") // --\u003e [\"value-1\", \"value-2\"]\n```\n\n\n## Hash (Map Object) - Delete Field\n\n```typescript\nhDelete(key: string, field: string)\n```\n\nDeletes a field of the map object.\n\n- Returns `undefined` if the key does not exist.\n- Returns `true` if the field existed and was deleted.\n- Returns `false` if the field did not exist.\n\n\u003e Do not use the hash functions with several very large amounts (megabytes) of data or blobs.\n\u003e This is because the entire data record with all fields is always read and written.\n\u003e It is better to use `setValues()` and `getValues()` for large amounts of data.\n\nInspired by: [https://docs.keydb.dev/docs/commands/#hdel](https://docs.keydb.dev/docs/commands/#hdel)\n\n### key\n\nThe key must be a string.\n\n### field\n\nThe field name must be a string.\n\n\n\n\n\n\n## Multiple Databases\n\nIt is no problem at all to use several databases and access them at the same time.\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\nimport { join } from \"node:path\"\n\nconst dbDir = join(__dirname, \"databases\")\nconst settingsPath = join(dbDir, \"settings.sqlite\")\nconst languagesPath = join(dbDir, \"languages.sqlite\")\n\nconst settingsStore = new BunSqliteKeyValue(settingsPath)\nconst languagesStore = new BunSqliteKeyValue(languagesPath)\n\n// Write settings\nsettingsStore.set(\"language\", \"de\")\nsettingsStore.set(\"page-size\", \"A4\")\nsettingsStore.set(\"screen-position\", {top: 100, left: 100})\n\n// Write languages\nlanguagesStore.set(\"de\", \"German\")\nlanguagesStore.set(\"en\", \"English\")\nlanguagesStore.set(\"it\", \"Italian\")\n\n// Read all settings\nconst settingItems = settingsStore.getItems()\nconsole.log(settingItems) // --\u003e [\n//   {key: \"language\", value: \"de\"},\n//   {key: \"page-size\", value: \"A4\"},\n//   {key: \"screen-position\", value: {top: 100, left: 100}},\n// ]\n\n// Read all languages\nconst languageValues = languagesStore.getValues()\nconsole.log(languageValues) // --\u003e [ \"German\", \"English\", \"Italian\" ]\n\n// Read current language\nconst languageKey = settingsStore.get(\"language\")\nconst currentLanguage = languagesStore.get(languageKey)\nconsole.log(`Current language: \"${currentLanguage}\"`) // --\u003e Current language: \"German\"\n\n// Close DBs\nsettingsStore.close()\nlanguagesStore.close()\n```\n\n\n## Database Transactions\n\nTransactions can be used to combine several database statements. \nThese combined database statements are processed much faster than \nif they were executed individually.\nThe more database statements are combined, the greater the speed advantage.\nYou can find more infos in the \n[Bun documentation](https://bun.sh/docs/api/sqlite#transactions).\n\n### Example\n\n```typescript\nimport { BunSqliteKeyValue } from \"bun-sqlite-key-value\"\n\nconst store = new BunSqliteKeyValue()\n\nstore.db.transaction(() =\u003e {\n    store.set(\"key1\", \"100\")\n    store.set(\"key2\", \"200\")\n    store.set(\"key3\", \"300\")\n})()\n\nstore.db.transaction(() =\u003e {\n    const value1 = store.get(\"key1\")\n    const value2 = store.get(\"key2\")\n    const value3 = store.get(\"key3\")\n    const total = value1 + value2 + value3\n    store.set(\"total1\", total)\n})()\n```\n\n\n## SQLite as base for a key value storage\n\nSQLite provides a solid and well-tested foundation.\nSQLite reliably takes care of saving and reading data - \nboth for short strings and for larger BLOBs. \nIt provides a robust foundation on which to build.\nEven if SQLite is not fully utilized and no relations between tables are required,\nthis is not a disadvantage.\n\nPlease give this [GitHub project](https://github.com/gerold-penz/bun-sqlite-key-value) \na ⭐ if this project is useful to you. Thank you very much!\nAnd if you speak German, here is my business homepage:\n[GP-Softwaretechnik](https://gp-softwaretechnik.at/)\nMaybe you will find something interesting for you there. 😃\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgerold-penz%2Fbun-sqlite-key-value","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgerold-penz%2Fbun-sqlite-key-value","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgerold-penz%2Fbun-sqlite-key-value/lists"}