{"id":27721320,"url":"https://github.com/idleberg/web-porridge","last_synced_at":"2025-04-27T10:05:11.895Z","repository":{"id":44547080,"uuid":"240375358","full_name":"idleberg/web-porridge","owner":"idleberg","description":"Feature-enhanced wrappers for the Storage and IndexedDB APIs","archived":false,"fork":false,"pushed_at":"2025-02-06T00:12:40.000Z","size":1229,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-27T10:04:53.006Z","etag":null,"topics":["html5-storage","local-storage","node-module","session-storage","storage","web-api","web-storage","web-storage-api"],"latest_commit_sha":null,"homepage":"https://www.npmjs.org/package/web-porridge","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/idleberg.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":"2020-02-13T22:09:24.000Z","updated_at":"2025-02-06T00:12:44.000Z","dependencies_parsed_at":"2023-02-18T01:30:30.207Z","dependency_job_id":"977ca4ef-5a7a-444c-aa44-10074c404f60","html_url":"https://github.com/idleberg/web-porridge","commit_stats":{"total_commits":375,"total_committers":3,"mean_commits":125.0,"dds":"0.053333333333333344","last_synced_commit":"a621441ddde9526083dc156dfd8dc927b80cd043"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idleberg%2Fweb-porridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idleberg%2Fweb-porridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idleberg%2Fweb-porridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idleberg%2Fweb-porridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idleberg","download_url":"https://codeload.github.com/idleberg/web-porridge/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251119619,"owners_count":21539196,"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":["html5-storage","local-storage","node-module","session-storage","storage","web-api","web-storage","web-storage-api"],"created_at":"2025-04-27T10:05:11.404Z","updated_at":"2025-04-27T10:05:11.885Z","avatar_url":"https://github.com/idleberg.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# web-porridge\n\n[![License](https://img.shields.io/github/license/idleberg/web-porridge?color=blue\u0026style=for-the-badge)](https://github.com/idleberg/web-porridge/blob/main/LICENSE)\n[![Version: npm](https://img.shields.io/npm/v/web-porridge?style=for-the-badge)](https://www.npmjs.org/package/web-porridge)\n[![Version: jsr](https://img.shields.io/jsr/v/@idleberg/porridge?style=for-the-badge)](https://jsr.io/@idleberg/porridge)\n[![CI: Node](https://img.shields.io/github/actions/workflow/status/idleberg/web-porridge/node.yml?logo=nodedotjs\u0026logoColor=white\u0026style=for-the-badge)](https://github.com/idleberg/web-porridge/actions/workflows/node.yml)\n[![CI: Deno](https://img.shields.io/github/actions/workflow/status/idleberg/web-porridge/deno.yml?logo=deno\u0026logoColor=white\u0026style=for-the-badge)](https://github.com/idleberg/web-porridge/actions/workflows/deno.yml)\n\nFeature-enhanced wrapper for both, [Storage API][] and [IndexedDB API][], sharing a common, familiar interface.\n\n**Features**\n\n- stores structured data\n- automatic (de)serialization\n- Object-level read \u0026 write access\n- data expiry\n- granular observability\n- other convenience methods\n\n## Installation\n\n`npm install web-porridge -S`\n\n## Usage\n\n### Import\n\n```ts\nimport { Porridge, PorridgeDB } from 'web-porridge';\n\nconst localPorridge = new Porridge();\nconst idb = new PorridgeDB();\n```\n\n### Instance\n\n#### `Porridge`\n\n```ts\nnew Porridge(storageArea: 'localStorage' | 'sessionStorage' = 'localStorage', eventName = 'porridge.didChange')\n```\n\n#### `PorridgeDB`\n\n```ts\nnew PorridgeDB(options?: {db: string; eventName = 'porridgeDB.didChange'; store: string})\n```\n\n### Methods\n\nAll methods and properties of the [Storage API][] have equivalents on `localPorridge` / `sessionPorridge`, completed by additional convenience methods as listed below.\n\nThe following methods are available for both, Storage and IndexedDB. However, the key difference is that the former API is synchronous, while the latter is _mostly_ asynchronous.\n\n**Table of contents**\n\n- [`setItem()`](#setitem)\n- [`getItem()`](#getitem)\n- [`removeItem()`](#removeitem)\n- [`clear()`](#clear)\n- [`key()`](#key)\n- [`length`](#length)\n- [`hasItem()`](#hasitem)\n- [`keys()`](#keys)\n- [`values()`](#values)\n- [`entries()`](#entries)\n- [`didExpire()`](#didexpire)\n- [`observe()`](#observe)\n\n#### `setItem()`\n\nUsage: `setItem(key: string, value: any, options?)`\n\nWhen passed a key name and value, will add that key to the given Storage object, or update that key's value if it already exists.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nlocalPorridge.setItem('firstItem', 'Hello World');\n\nlocalPorridge.setItem('secondItem', { name: 'John Appleseed' });\nlocalPorridge.setItem('secondItem', 'Ada Lovelace', { prop: 'name' });\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nawait idb.setItem('firstItem', 'Hello World');\n\nawait idb.setItem('secondItem', { name: 'John Appleseed' });\nawait idb.setItem('secondItem', 'Ada Lovelace', { prop: 'name' });\n```\n\n\u003c/details\u003e\n\n#### `getItem()`\n\nUsage: `getItem(key: string, options?)`\n\nWhen passed a key name, will return that key's value, or `null` if the key does not exist, in the given Storage object.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nlocalPorridge.getItem('firstItem');\nlocalPorridge.getItem('secondItem', { prop: 'dot.notation.property' });\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nawait idb.getItem('firstItem');\nawait idb.getItem('secondItem', { prop: 'dot.notation.property' });\n```\n\n\u003c/details\u003e\n\n#### `removeItem()`\n\nUsage: `removeItem(key: string, options?)`\n\nWhen passed a key name, will remove that key from the given Storage object if it exists.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nlocalPorridge.removeItem('firstItem');\nlocalPorridge.removeItem('secondItem', { prop: 'dot.notation.property' });\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nawait idb.removeItem('firstItem');\nawait idb.removeItem('secondItem', { prop: 'dot.notation.property' });\n```\n\n\u003c/details\u003e\n\n#### `clear()`\n\nUsage: `clear()`\n\nClears all keys stored in a given Storage object.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nlocalPorridge.clear();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nawait idb.clear();\n```\n\n\u003c/details\u003e\n\n#### `key()`\n\nUsage: `key(index: number)`\n\nWhen passed a number n, returns the name of the nth key in a given `Storage` object.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nlocalPorridge.key(0);\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nawait idb.key(0);\n```\n\n\u003c/details\u003e\n\n#### `length`\n\nUsage: `length`\n\nReturns the number of data items stored in a given Storage object.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nlocalPorridge.length;\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nawait idb.length;\n```\n\n\u003c/details\u003e\n\n#### `hasItem()`\n\nUsage: `hasItem(key: string)`\n\nWhen passed a key name, returns a boolean indicating whether that key exists in a given Storage object.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nlocalPorridge.hasItem('firstItem');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nawait idb.hasItem('firstItem');\n```\n\n\u003c/details\u003e\n\n#### `keys()`\n\nUsage: `keys()`\n\nReturns an array of a given object's Storage own enumerable property names, iterated in the same order that a normal loop would.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nlocalPorridge.keys();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nawait idb.keys();\n```\n\n\u003c/details\u003e\n\n#### `values()`\n\nUsage: `values()`\n\nReturns an array of a given Storage object's own enumerable property values, iterated in the same order that a normal loop would.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nlocalPorridge.values();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nawait idb.values();\n```\n\n\u003c/details\u003e\n\n#### `entries()`\n\nUsage: `entries()`\n\nReturns an array of a given object's own enumerable string-keyed property `[key, value]` pairs, iterated in the same order that a normal loop would.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nlocalPorridge.entries();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nawait idb.entries();\n```\n\n\u003c/details\u003e\n\n#### `didExpire()`\n\nUsage: `didExpire(key: string)`\n\nWhen passed a key name, will return whether that key has expired.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nlocalPorridge.didExpire('firstItem');\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nawait idb.didExpire('firstItem');\n```\n\n\u003c/details\u003e\n\n#### `observe()`\n\nUsage: `observe(key: string, callback: function)`\n\nWhen passed a key name and callback function, it will listen to changes to the given Storage object's value.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eStorage\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nconst unobserve =localPorridge.observe('demo', ({ key, newValue }) =\u003e {\n\tconsole.log(`${key} has changed to:`, newValue);\n});\n\n// Later, to stop observing\nunobserve();\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eIndexedDB\u003c/strong\u003e\u003c/summary\u003e\n\n```ts\nconst unobserve = idb.observe('demo', ({ key, newValue }) =\u003e {\n\tconsole.log(`${key} has changed to:`, newValue);\n});\n\n// Later, to stop observing\nunobserve();\n```\n\n\u003c/details\u003e\n\n### Options\n\n#### `expires`\n\nType: `string`\n\nSets an expiry date for the storage value. Can be anything that can be parsed by `new Date()`.\n\n#### `prop`\n\nType: `string`\n\nSpecifies an object property as a dot notation string. Allows granular reads and updates.\n\n## License\n\nThis work is licensed under [The MIT License](LICENSE).\n\n[dot notation]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors#Dot_notation\n[storage api]: https://developer.mozilla.org/en-US/docs/Web/API/Storage\n[indexeddb api]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidleberg%2Fweb-porridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidleberg%2Fweb-porridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidleberg%2Fweb-porridge/lists"}