# store2: localStorage and sessionStorage with JSON and namespaces

> store2 wraps browser storage in a common API for localStorage, sessionStorage, page-lifetime data, and custom Storage implementations. It suits JavaScript applications that need JSON serialization and compact storage operations, but its browser-only design and JSON model limit larger or server-side use.

**nbubna/store** — A better way to use localStorage and sessionStorage

- Repository: https://github.com/nbubna/store
- Stars: 1,943 · Forks: 114
- Language: JavaScript
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/nbubna-store

## Why store2 wraps browser storage

store2 addresses the repetitive parts of using the browser's `localStorage` and `sessionStorage` directly. Its main function supports setting, retrieving, transacting, clearing, iteration, and bulk operations. Values are stringified on writes and parsed on reads, so application code can work with JavaScript objects instead of handling JSON text at every call site.

The default store uses `localStorage`, which persists according to browser storage rules. `store.session` exposes the same API over `sessionStorage`, while `store.page` holds non-persistent information until the page reloads. An application can also register another backend through `store.area(name, customStorageObject)`, provided that the object implements the browser `Storage` interface. That extension point is useful when another library supplies a compatible storage implementation.

The project is for developers who need a small storage facade rather than a separate database, synchronization service, or application state framework. store2 does not document cross-tab synchronization, expiration, quotas, or server persistence. Its documented value comes from a more convenient API and shared behavior across storage areas.

## The callable API behind store2

The main `store` function dispatches based on its arguments. Passing a key and data performs a set, while passing only a key performs a get. An object argument triggers `setAll`, no argument returns all entries, a function iterates entries, and `false` clears the selected area. This compact form is useful for simple operations, although the explicit methods are easier to scan in larger codebases.

The explicit API includes `store.set`, `store.get`, `store.transact`, `store.has`, `store.remove`, `store.add`, `store.keys`, `store.size`, and `store.clear`. Retrieval methods return a caller-provided alternate value when no stored value is available. Set methods return the previous value by default. Supplying `false` as the optional overwrite argument prevents an existing key from being replaced.

A write passes through JSON serialization before reaching the selected storage backend, and a read parses the stored string. `transact` reads the current value, passes it to a callback, and writes the returned value back. If the callback returns `undefined`, store2 saves the original value, allowing a callback to mutate an object and persist that mutation without returning it.

Namespacing is part of the project description, although the README does not show the configuration syntax. The repository layout includes source, distribution, TypeScript declaration, test, and build files. Based on `package.json`, consumers load `dist/store2.js` through the package's `main` entry and can access declarations from `index.d.ts`.

## Transactions and iteration in store2

`transact` is the clearest operation when an application needs to derive a new value from the stored one. The callback receives the current value, or an alternate when the key is absent, and the result becomes the next stored value. This avoids separating a read and write in application code, although store2 does not document transactional isolation between browser contexts.

The README gives this mutation pattern:

```javascript
store.transact(key, function(obj) {
    obj.changed = 'newValue';// this change will be persisted
});
```

Because an `undefined` return preserves the original value, the callback can modify nested properties and omit a return statement. The function will not persist in-memory changes if the stored data cannot be parsed or if the mutation path is not reached. The README does not document retry, conflict, or rollback behavior for failed transactions.

Iteration uses `store.each`. Its callback receives the key and parsed value, while an optional third argument supplies a caller-defined value. Returning `false` stops iteration immediately. The documented pattern is:

```javascript
store.each(function(key, value) {
    console.log(key, '->', value);
    if (key === 'stopLoop') {
        return false;// this will cause each to stop calling this function
    }
});
```

`store.keys` returns key names, and `store.size` reports the number of keys rather than the size of their serialized data. For large collections, this distinction matters because a low key count does not imply low storage consumption.

## Installing store2 and selecting a storage area

The README documents installation from npm, NuGet, or downloadable distribution files. For an npm-based browser project, the documented package command is:

```bash
npm install store2
```

The package declares `dist/store2.js` as its main entry and `index.d.ts` as its types entry. The precise bundler or module-loading step depends on the host application, and the README does not document a separate browser bundler configuration.

The README also gives this NuGet installation command:

```powershell
Install-Package store2
```

store2 keeps the same method surface across storage areas. The default `store` uses browser `localStorage`. `store.session` uses `sessionStorage`, while `store.page` is for non-persistent information that lasts until page reload. The same methods are also available on a custom area registered through `store.area(name, customStorageObject)`.

The README documents this session-backed write:

```javascript
store.session("addMeTo", "sessionStorage");
```

This stores the string `sessionStorage` under `addMeTo` in `sessionStorage`. The README states that `store.local === store`. A project can therefore choose storage lifetime by changing the storage area rather than repeating backend-specific calls.

## JSON revivers and replacers for richer values

Plain JSON does not preserve every JavaScript type automatically. The README allows retrieval methods to accept a reviver function in place of the usual alternate value. The reviver receives each key and value, including nested values, which allows callers to define custom parsing. The documentation points to `JSON.parse` behavior and uses `Date` values as the motivating example.

The corresponding write path supports a replacer through the optional overwrite parameter. A replacer receives each key and value, including nested values, before serialization. The README names `Map` and `Set` as cases where a custom replacement rule may be useful. Global handlers can also be assigned through `store._.revive` and `store._.replace`.

These hooks add control, but they also place an important limitation on evaluation. A custom replacer and reviver must be consistent across every writer and reader of the same key. If one page writes with a replacement rule and another page reads without the matching revival rule, the resulting application state depends on that mismatch. The README does not document schema versioning, per-key handler registration, or migration helpers.

The customization mechanism is useful for controlled application schemas, but it does not make store2 a general object persistence system. A team adopting it should decide how values are represented before sharing a key between pages or components.

## Where store2 is the wrong storage choice

store2 is not suitable when application requirements exceed browser Web Storage. The package targets `localStorage`, `sessionStorage`, page-lifetime memory, and compatible storage objects. It is not a server database, does not provide durable remote storage, and does not document cross-tab synchronization. Data in `sessionStorage` is tied to the browser's session behavior rather than application-level accounts or devices.

The JSON wrapper is a poor fit for large binary values, streaming files, or payloads that must remain typed without conversion logic. Although custom replacers and revivers can address some rich objects, those hooks require application code to define the representation. The project does not document a size calculation API. Although `store.size()` returns the number of keys, it does not report the browser quota or serialized byte total.

Namespacing can also become a design issue. The repository is built around a store-level namespace and extensions. It is a reasonable fit when several widgets share one browser origin and need a common prefix. It is less suitable when an application needs independently versioned schemas, automatic expiry, atomic updates across tabs, or per-record access control. The README does not document rollback, expiration, or conflict-resolution mechanisms, so those behaviors should not be inferred from the word `transact`.

A second boundary is data ownership. Clearing a selected area affects all values managed by that store within the browser's storage model. `store.clearAll()` is documented as clearing all areas while remaining namespace sensitive. Applications that share an origin or storage area need explicit ownership decisions before using bulk clear operations.

## store2 compared with direct Web Storage access

Direct Web Storage access is the main alternative. Native `localStorage.setItem`, `getItem`, `removeItem`, and `sessionStorage` calls expose the browser's string-based `Storage` interface without an added wrapper. That approach is simpler when an application has only a few keys and already handles serialization explicitly. It also avoids adding store2's API and namespace decisions.

store2 changes the implementation approach by adding argument-based dispatch, automatic JSON parsing, bulk helpers, transactions, iteration, custom revivers and replacers, and several storage areas behind one interface. Its `store.session`, `store.page`, and `store.area` model can prevent different parts of an application from issuing inconsistent storage calls. The package also ships TypeScript declarations and a NuGet package, according to the repository files and README.

The trade-off is abstraction. Direct access makes the serialized representation visible at each call site, while store2 can hide it behind object-shaped operations. store2 is the better fit when the application accepts JSON semantics and wants those helpers. Direct Web Storage is easier to reason about when the data shape is primitive, interoperability with native storage is required, or the team prefers to avoid a wrapper dependency.

Neither approach documented here supplies a server-side database or cross-tab synchronization. The decision is primarily about API convenience, serialization policy, and whether the application can keep its data within browser storage limits.

## Maintenance signals and upgrade work in store2

The repository is not archived, and the last push was on 2026-08-23. That is a recent maintenance signal, but it does not establish a release cadence. The repository has no GitHub releases. Its `package.json` reports version `2.14.4`, identifies the license as MIT, and defines `npm test` as a Grunt and QUnit test script. The development dependency set includes PhantomJS-related packages, which reflects the browser test setup recorded in the project metadata.

For upgrades, the repository includes `package-lock.json`, `src`, `dist`, tests, a Gruntfile, and TypeScript declarations. Consumers can inspect the source and generated distribution files rather than relying only on a hosted download. The package's `prepublishOnly` script runs the Grunt build and performs Git commit, tag, and push operations as part of publishing. That is release infrastructure owned by maintainers, not a command intended for routine application upgrades.

The MIT license permits use, modification, and distribution under its terms, subject to the license text. It does not remove the need to check dependency licenses or assess browser compatibility for the application. Before upgrading, inspect `package.json`, the generated `dist` files, and the project's test target rather than assuming that a newer package preserves the same serialization behavior.

## Conclusion

store2 is appropriate for browser applications that want compact, namespaced access to localStorage or sessionStorage and can accept JSON serialization semantics. It is a poor fit for server-side state, large binary payloads, or applications requiring transparent Date, Map, and Set preservation. Before adoption, verify whether its namespace model matches the application data model and confirm that its browser execution target fits the supported browsers. The repository is not archived and its last push was on 2026-08-23, but it has no GitHub releases.

## FAQ

### How do I install store2?

The README documents `npm install store2`. It also provides `Install-Package store2` for NuGet and links to downloadable `store2.js` and `store2.min.js` files.

### How do I use store2 with sessionStorage?

Use `store.session` instead of the default `store` API. It exposes the same storage methods over `sessionStorage`.

### Does store2 support Date and Map values?

The README documents custom JSON revivers and replacers for richer values, including `Date` and `Map`. Their serialization and revival require application-supplied functions.

## Sources

- [Issues](https://github.com/nbubna/store/issues)
- [License: MIT](https://github.com/nbubna/store/blob/master/LICENSE)
- [nbubna/store on GitHub](https://github.com/nbubna/store)
- [README](https://github.com/nbubna/store/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nbubna-store
