Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
The store2 npm package is a simple, lightweight JavaScript library for cross-browser local storage with a simple but powerful API. It provides an easy way to store, retrieve, and manage data in the browser's local storage and session storage, with additional features such as namespacing and cross-tab communication.
Basic storage operations
Perform basic local storage operations such as setting, getting, removing, and clearing all items.
{"set": "store.set('user', {name: 'Marcus'})", "get": "store.get('user')", "remove": "store.remove('user')", "clearAll": "store.clearAll()"}
Namespacing
Create a namespace to group related data and perform operations within that namespace.
{"createNamespace": "var userStore = store.namespace('user')", "namespaceSet": "userStore.set('info', {name: 'Marcus'})", "namespaceGet": "userStore.get('info')"}
Cross-tab communication
Enable cross-tab communication by setting a flag that will trigger the storage event listener when data is changed.
{"setListen": "store.set('user', {name: 'Marcus'}, true)", "onStorage": "window.addEventListener('storage', function(e) { console.log('storage changed', e.key); })"}
Additional storage methods
Use additional methods to retrieve all stored items, iterate over them, or perform a transactional operation on a stored object.
{"getAll": "store.getAll()", "each": "store.each(function(value, key) { console.log(key, '==', value); })", "transact": "store.transact('user', function(user) { user.visits = (user.visits || 0) + 1; })"}
js-cookie is a simple, lightweight JavaScript API for handling browser cookies. It allows you to create, read, and delete cookies with ease. While store2 focuses on local and session storage, js-cookie is specifically designed for cookie storage, which can be useful for storing data that needs to be sent to the server on each request.
redux-persist is a library allowing to save a Redux store state in a persistent storage and rehydrate it on app start. It is more specialized than store2 as it is designed to work with Redux applications, providing a seamless way to persist and rehydrate the Redux state tree.
A feature-filled and friendly way to take advantage of localStorage and sessionStorage (JSON, namespacing, extensions, etc).
Download: store2.min.js or store2.js
NPM: npm install store2
NuGet: Install-Package store2
The main store function can handle set
, get
, transact
, setAll
, getAll
, each
, and clear
actions directly. Respectively, these are called like so:
store(key, data); // sets stringified data under key
store(key); // gets and parses data stored under key
store(key, fn[, alt]); // run transaction function on/with data stored under key
store({key: data, key2: data2}); // sets all key/data pairs in the object
store(); // gets all stored key/data pairs as an object
store((key, data)=>{ }); // calls function for each key/data in storage, return false to exit
store(false); // clears all items from storage
Parameters in [brackets] are optional. There are also more explicit and versatile functions available:
store.set(key, data[, overwrite]); // === store(key, data);
store.setAll(data[, overwrite]); // === store({key: data, key2: data});
store.get(key[, alt]); // === store(key);
store.getAll([fillObj]); // === store();
store.transact(key, fn[, alt]); // === store(key, fn[, alt]);
store.clear(); // === store(false);
store.has(key); // returns true or false
store.remove(key[, alt]); // removes key and its data, then returns the data or alt, if none
store.each(fn[, fill]); // === store(fn); optional call arg will be 3rd fn arg (e.g. for gathering values)
store.add(key, data[, replacer]); // concats, merges, or adds new value into existing one
store.keys([fillList]); // returns array of keys
store.size(); // number of keys, not length of data
store.clearAll(); // clears *ALL* areas (but still namespace sensitive)
Passing in false
for the optional overwrite parameters will cause set
actions to be skipped
if the storage already has a value for that key. All set
action methods return the previous value
for that key, by default. If overwrite is false
and there is a previous value, the unused new
value will be returned.
Functions passed to transact
will receive the current value for that key as an argument or
a passed alternate if there is none. When the passed function is completed, transact will save the returned value
under the specified key. If the function returns undefined
, the original value will be saved.
This makes it easy for transact functions to change internal properties in a persistent way:
store.transact(key, function(obj) {
obj.changed = 'newValue';// this change will be persisted
});
Functions passed to each
will receive the key as first argument and current value as the second; if a fill
parameter is specified, it's value will be the third argument for every call (few should ever
need a fill
parameter). If the function returns false
at any point during the iteration, the
loop will exit early and not continue on to the next key/value pair.
store.each(function(key, value) {
console.log(key, '->', value);
if (key === 'stopLoop') {
return false;// this will cause each to stop calling this function
}
});
All retrieval functions which take an optional alt
parameter can also use that parameter to specify a "reviver" function. These receive each key and value (yes, nested ones too) as arguments and allow you to provide an alternate means of parsing that string. This is particularly useful for rich objects like Date
types. See MDN's JSON.parse docs for more information and examples. Alternately, you can set a global reviver to the store._.revive
property to handle all get
, getAll
, remove
, and transact
calls.
Likewise, setter functions which take an optional overwrite
parameter can also use that parameter to accept a "replacer" function that receives each key and value (yes, nested ones too) as arguments and allow you to provide an alternate means of stringifying the values. This is particularly useful for rich objects like Map
or Set
. See MDN's JSON.stringify docs for more information and examples. Alternately, you can set a global replacer to the store._.replace
property to handle all set
, setAll
, add
, and transact
calls.
For getAll
and keys
, there is the option to pass in the object or list, respectively,
that you want the results to be added to. This is instead of an empty list.
There are only a few special cases where you are likely to need or want this,
in general, most users should ignore these optional parameters.
These both use the second, optional argument each
function,
which is also a niche feature. The value
argument is passed as
the second arg to the callback function (in place of the data associated with the current key)
and is returned at the end. Again, most users should not need this feature.
All of these use the browser's localStorage (aka "local"). Using sessionStorage merely requires
calling the same functions on store.session
:
store.session("addMeTo", "sessionStorage");
store.local({lots: 'of', data: 'altogether'});// store.local === store :)
There is also a store API automatically available for keeping non-persistent information, meant only to last until page reload.
store.page("until","reload");
All the specific get
, set
, etc. functions are available on store.session
, store.local
, and store.page
, as well as any other storage facility registered via store.area(name, customStorageObject)
by an extension, where customStorageObject must implement the Storage interface. This is how store.old.js extends store.js to support older versions of IE and Firefox.
If you want to put stored data from different pages or areas f your site into separate namespaces,
the store.namespace(ns)
function is your friend:
var cart = store.namespace('cart');
cart('total', 23.25);// stores in localStorage as 'cart.total'
console.log(store('cart.total') == cart('total'));// logs true
console.log(store.cart.getAll());// logs {total: 23.25}
cart.session('group', 'toys');// stores in sessionStorage as 'cart.group'
The namespace provides the same exact API as store
but silently adds/removes the namespace prefix as needed.
It also makes the namespaced API accessible directly via store[namespace]
(e.g. store.cart
) as long as it
does not conflict with an existing part of the store API.
The 'namespace' function is one of three "extra" functions that are also part of the "store API":
store.namespace(prefix);// returns a new store API that prefixes all key-based functions
store.isFake([force]);// test or set whether localStorage/sessionStorage or an in-memory, 'fake' storage is used
store.namespace
can also take extra params to only create the namespace in the called-on storage area, and
to pass in an alternate namespace delimiter for advanced use-cases (e.g. store.page.namespace("subpage", true, ":")
).
If localStorage or sessionStorage are unavailable, they will be faked to prevent errors, but data stored will NOT persist beyond the life of the current document/page. Use the store.old.js extension to add persistent backing for the store API in ancient browsers.
isFake(true|false)
is particularly useful to force use of a temporary, fake storage in testing situations,
to prevent cluttering actual storage.
These mostly could use further documentation and abuse...er...testing. Contributions are welcome! In particular, any ES6 user interested in making these importable in ES6 would be appreciated.
set()
callsstore.push(key, v1, v2)
).store.cookie('num',1)
to make sharing with backend easier.store.foo == store.get('foo')
)store.get('key.property')
)store.async
duplicate to each store and namespace that performs functions asynchronously and returns a Promise that resolves when complete.store.cookies.get('user')
)To write your own extension, you can use or carefully override internal functions exposed as store._
.
In particular, the store._.fn(fnName, fn)
method is available to automatically add your new function
to every instance of the store
interface (e.g. store
, store.session
and all existing and future namespaces). Take care using this, as it will override existing methods.
Here is a simple example:
(function(_) {
_.fn('falsy', function(key) {
return !this.get(key);
});
_.fn('truthy', function(key) {
return !this.falsy(key);
});
})(store._);
This extension would be used like so:
store('foo', 1);
store.falsy('foo'); // returns false
store.session('bar', 'one');
store.session.truthy('bar'); // return true;
const widgetStore = store.namespace('widget');
widgetStore.falsy('state'); // returns true
clear()
in fake storage (thx to Martin Kluska)index.d.ts
in root to provide TypeScript supporteach(fn,value)
, getAll(fillObj)
, and keys(fillList)
to support some advanced/corner casesadd(key, data)
for common case of saving a combination of existing and new data. Fix issue #60.store(fn)
shortcut for store.each
, copy properties when inheriting, and make store.each(fn, fill)
always send fill as 3rd arg instead of replacing values.store.page
to provide page scope storage to complement local and session scope storage. (Issue #69)store.get(key, reviveFn)
and ```store._.revive`` to support parsing for rich types (e.g. Date)store.get(key, alt)
store.set(key, value, replacerFn)
, store._replace
, and isFake([force])
to support stringifying rich types and easier testing. And cookie-based extensions for using store backed by a single 'store' cookie or store API for all cookies.set
that broke store.cache.js, and allow namespace delimiter to be passed to namespace(name, thisAreaOnly, delim)
for a single namespace, to avoid conflicts.index.d.ts
typings.FAQs
Better localStorage
The npm package store2 receives a total of 2,139,443 weekly downloads. As such, store2 popularity was classified as popular.
We found that store2 demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.