SkillAgentSearch skills...

LocalDataStorage

💼 A handy wrapper for HTML5 localStorage that seamlessly gets/sets common data types (Array, BigInt, Boolean, Date, Float, Integer, null, Object and String); provides simple data scrambling; intelligently compresses strings (saving storage space); permits query by key as well as query by value and promotes shared storage segmentation in the same domain. Key names and values are multi-byte Unicode-safe, and a key value change will fire an event you can subscribe to (even on a single page).

Install / Use

/learn @macmcmeans/LocalDataStorage

README

💼 localDataStorage<br>

Maintenance License Minified Latest UTF8 SU.PPORT.ME

TL;DR

Directly use in localStorage with no conversion. <br> <br>

Highlights

This is a synchronous JavaScript interface for the HTML5 localStorage API that--

  1. transparently sets/gets key values using data "types" such as Array, BigInt, Boolean, Date, Float, Integer, Object and String;
  2. provides lightweight data obfuscation;
  3. intelligently compresses strings (to save storage space);
  4. facilitates robust lookup including query by key (name), query by (key) value and query by existence (boolean check);
  5. enforces segmented shared storage within the same domain by prefixing keys;
  6. lets you respond to localStorage change events on the same page/tab that fired them;
  7. broadcasts change events across the origin for the benefit of other windows/tabs;
  8. lets you easily work with arrays using dedicated Array Keys; and
  9. offers Memory Keys (that can be backed up to disk) for the fastest read times possible.

<br> <br> Version 3.0.0<br> Author: W. “Mac” McMeans<br> Date: 12 AUG 2022 <br> <br>

Trusted Installation

Include via CDN

<script
    src="https://cdn.jsdelivr.net/gh/macmcmeans/localDataStorage@master/localDataStorage-3.0.0.min.js" 
    integrity="sha512-dEhk3bL90qpWkcHCJDErHbZEY7hGc4ozmKss33HSjwMeSBKBtiw/XVIE7tb5u+iOEp6dTIR9sCWW7J3txeTQIw==" 
    crossorigin="anonymous"
></script>

Since the source file is delivered from a repository over which we have no control, best practices demand we do not trust it. Thus we use Subresource Integrity (SRI) to prevent tampering.

Unlike the BrowseAloud story, my library is a static, self-contained resource which can be fully protected by SRI. <br> <br>

Application:

Primary usage is the ability to seamlessly set/get keys for typical data types without having to perform conversion in your own logic. Toss out an integer and have it returned. Throw an array into storage and get it back, including the ability to add and remove elements. Are you also working with dates, booleans or objects? No problem. While it’s not rocket science to convert, track and restore your own data, letting the interface handle that chore for you is exceptionally convenient. It also saves you the hassle having to incorporate conversion logic in your application. To track a data type, storage management requires one additional byte of memory overhead per key value, so an eight-byte array, for example, will be stored using nine bytes.

<b>Data Protection</b><br>Since localStorage data resides in a client environment where the information is not protected from access or tampering, this data can be rendered unintelligible at the expense of a small amount of memory overhead. Depending on your application, this may be worth the tradeoff. To hide your data, key values may be obfuscated using safeset/safeget. A master scramble key may be set globally, or individual scramble keys may be used per each safeset/safeget call. Scramble keys can be any value and of any type (array, boolean, date, float, integer, etc.) Key values that have been safeset with an individual scramble key can always be retrieved, but cannot be reconstructed apart from the exact scramble key with which they were obfuscated. For convenience, the global scramble key is stored in the interface. For security, individual scramble keys are not. The global scramble key may be accessed using setscramblekey/getscramblekey methods. Individual scramble keys must be remembered.

Scrambling is not encryption. For example, no attempt is made to conceal data lengths by artificially padding to a minimum length. This would be counterproductive to minimizing memory usage.

<b>Compression</b><br>Strings are intelligently compressed on‑the‑fly when storing. This means they are first analyzed to determine whether compression would lower the actual byte count (not string length) needed for storage, and if so, are silently compressed for you. This works well for common English texts (short‑length, 7‑bit ASCII), and not much else. If desired, you may manually crunch/uncrunch your own key values.

<b>Robust Access</b><br>One may query by key (the standard way) or query by existence (haskey checks if the key is in the store while hasval checks if the store contains the value). You can query for duplicate values with listdupes and showdupes. Convenience methods prevent writing over an existing key (softset) and permit deleting a key immediately upon retrieval (chopget). You can easily query and update an array key using push/pull and contains without the need for external array logic. Key values can be checked for their data type, for example, using isfloat, and keys can be renamed (rename). Lastly, bypass methods (forceset/forceget) permit accessing localStorage directly.

<b>Storage Management</b><br>Since HTML5 localStorage is accessible to all processes running in the browser for the domain visited, it is advisable to have an interface that segments access. To that end, the use of prefixed keys is strongly encouraged, and localDataStorage will only read/write/delete its own values. Unlike the HTML5 API, there is no method in the interface to clear all storage keys, only all prefixed keys. At any time, memory usage can be tracked against key values and key names, for example, using valbytes or keybytes.

The domain of operation for HTML5 localStorage is specific to the protocol, host & port; and multiple instances of localDataStorage can be run against the same domain at the same time. It is emoji‑friendly 🤪🤷‍♂️💖👍, which is to say that key names and their values, as well as scramble keys and storage prefixes, are multibyte Unicode‑safe.

Events

The native localStorage change event is... lacking. Per the misguided whims of the interweb gods, a web page in your browser isn’t permitted to listen to change events that it alone triggers. However, in the event you'd like to keep an ear out for changes, localDataStorage will let you. The interface fires a custom event on key value changes, such as those made by the chopget, clear, forceset, remove, rename, safeset, set and softset methods. The event returns an activity timestamp and message, as well as expected details about the affected key with its old and new values (and old and new data types, etc.) Insert your own function here to catch the changes. This code snippet shows what's exposed so you can respond accordingly:

const nowICanSeeLocalStorageChangeEvents = function( e ) {
    console.log(
        "subscriber: " + e.currentTarget.nodeName + "\n" +
        "date: "       + e.detail.date            + "\n" +
        "timestamp: "  + e.detail.timestamp       + "\n" +
        "prefix: "     + e.detail.prefix          + "\n" +
        "message: "    + e.detail.message         + "\n" +
        "method: "     + e.detail.method          + "\n" +
        "old key: "    + e.detail.oldkey          + "\n" +
        "new key: "    + e.detail.newkey          + "\n" +
        "old value: "  + e.detail.oldval          + "\n" +
        "new value: "  + e.detail.newval          + "\n" +
        "old type: "   + e.detail.oldtype         + "\n" +
        "new type: "   + e.detail.newtype         + "\n" +
        "old base: "   + e.detail.oldbase         + "\n" +
        "new base: "   + e.detail.newbase
    );

    // respond to key change by passing key name
    myCustomChangeFunction( e.detail.oldkey ); 
}

document.addEventListener(
    "localDataStorage"
    , nowICanSeeLocalStorageChangeEvents
    , false
);

<br> <br>

Dependencies:

There are no external dependencies.

Internally, obfuscation is supported by fisherYatesDurstenfeldKnuthShuffle and aleaPRNG (my own libraries). <br> <br>

SemVer:

Recognizing there is

Related Skills

View on GitHub
GitHub Stars89
CategoryCustomer
Updated2mo ago
Forks15

Languages

JavaScript

Security Score

100/100

Audited on Jan 23, 2026

No findings