JSPM

with-cache-normalization

1.0.5
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 4
  • Score
    100M100P100Q42548F
  • License MIT

🗜️ normalize your cache -> get automatic cache updates ✨

Package Exports

  • with-cache-normalization
  • with-cache-normalization/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (with-cache-normalization) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

with-cache-normalization

🗜️ normalize your cache -> get automatic cache updates ✨

install

npm install with-cache-normalization

use

lets say you're starting with a cache that stores references to ships

without normalization, it will operate something like this

const value = {
  ships: [
    new Ship({ id: 1, name: 'boaty mcboatface' }),
    new Ship({ id: 2, name: 'sea biscuit' }),
    new Ship({ id: 1, name: 'boaty mcboatface' })
  ],
};
cache.set('__key__', value);
expect(cache.get('__key__')).toEqual(value) // true, like we would expect

and the cache store would now contain something like this

{
  '__key__': {
    ships: [
      new Ship({ id: 1, name: 'boaty mcboatface' }),
      new Ship({ id: 2, name: 'sea biscuit' }),
      new Ship({ id: 1, name: 'boaty mcboatface' }
    ]
  }
}

🗜️ add normalization to a cache

we can leverage normalization to reference those ships via foreign key, like in a relational database

with normalization, it will operate like this

import { withNormalization, normalizeDomainObjectReferences } from 'with-cache-normalization';

const value = {
  ships: [
    new Ship({ id: 1, name: 'boaty mcboatface' }),
    new Ship({ id: 2, name: 'sea biscuit' }),
    new Ship({ id: 1, name: 'boaty mcboatface' })
  ],
};
const cacheWithNormalization = withNormalization(
  cache,
  {
    normalize: normalizeDomainObjectReferences,
  }
)
cacheWithNormalization.set('__key__', value);
expect(cacheWithNormalization.get('__key__')).toEqual(value) // still true, as the .get automatically denormalizes the results

and the cache store would now contain something like this

 {
   '__key__': {
     ships: [
       '.cache.ref.Ship.1',
       '.cache.ref.Ship.2',
       '.cache.ref.Ship.1',
     ]
   },
  '.cache.ref.Ship.1}': new Ship({ id: 1, name: 'boaty mcboatface' ),
  '.cache.ref.Ship.2}': new Ship({ id: 2, name: 'sea biscuit' )
 }

this provides the following advantages

  • 🗜️ smaller cache size: when the same entities are referenced more than once, only the reference is duplicated
  • ✨ automatic cache updates: when any cache.set updates the same referenced entity, all will dereference the latest value

note: the normalizeDomainObjectReferences method comes out of the box with this library, since domain-object normalization is a common usecase

🎈 add only denormalization to a cache

you may find a scenario where you want to denormalize values from a cache that you are not writing to (e.g., with-cache-normalization)

in this scenario, you likely wont have access to the method used to normalize the values

not a problem, you can denormalize entries in the cache without needing to know this method

for example, lets say you're accessing the same cache state as with the normalized ships from above

const cacheWithDenormalization = withNormalization(cache)
cacheWithDenormalization.get('__key__');

the above would return the fully hydrated, denormalized value

{
  ships: [
    new Ship({ id: 1, name: 'boaty mcboatface' }),
    new Ship({ id: 2, name: 'sea biscuit' }),
    new Ship({ id: 1, name: 'boaty mcboatface' })
  ],
};

🌀 add serialization to a string only cache

a common situation you may find yourself in is attempting to add normalization to a cache which only accepts strings

since normalization requires object input in order to recursively traverse the data you're attempting to cache, it can't operate directly on a cache that only accepts strings

to solve for this, simply add serialization to the cache with the withSerialization utility

for example

const ship = new Ship({ id: 3, name: 'nacho boat' })

// lets say your original cache only accepts strings
cache.set('__key__', ship) // 🚫 type error

// easily add serialization
const cacheWithSerialization = withSerialization(cache) // defaults to JSON.stringify + JSON.parse

// now, you can write any data to this cache
cacheWithSerialization.set('__key__', ship) // ✅ serialized when setting

// and, when you read it, it will be deserialized
const cached = cacheWithSerialization.get('__key__')
expect(cached).toEqual(ship) // ✅ deserialized when getting