Data Capsule
Sane key/value store access layer
Some more use cases
- Local cache of blobs of data
- Draft / Unsaved changes
- Passing data between pages
How do we remember?
- DOM Storage (aka sessionStorage / localStorage)
- Easy, Fast, (Mostly) reliable
- Will not persistent between machines
- Might be cleared by user
- Usually would be used where it is not a big deal if data is lost (or if it is short term storage)
- Remote DB
- Usually would be used where it is important to remember
DOM Storage
localStorage / sessionStorage
Session Storage is a lie!
Session cookie is even a worse lie
We never use session storage/cookie
DOM Storage is per origin
- Storage is shared between all the pages that run on the same origin
- Storage is shared between all the people who use the same browser (think internet cafe, universities)
- Storage is shared between all the sites our same person builds
- Storage is *not* shared between http://www.wix.com and https://www.wix.com
- Storage is *not* shared between https://de.wix.com and https://fr.wix.com
- Problems: global namespace, shared quota (5MB), privacy
DOM Storage doesn't always work
- Incognito
- Quota exceeded
- Biggest problem: 3rd party storage policies
Conclusions
- Access to local storage needs to be namespaced
- Access to local storage needs to be scoped
- Local storage quota needs to be managed
- Access to local storage needs to be protected
- Wanted: better abstraction!
Introducing
Data Capsule
(aka wixStorage/wixCache)
import {LocalStorageCapsule} from 'data-capsule';
const capsule = new LocalStorageCapsule({namespace: 'engage'});
await capsule.setItem('shahata', 123);
console.log(await capsule.getItem('shahata')); // logs 123
import {DataCapsule, LocalStorageStrategy} from 'data-capsule';
const capsule = new DataCapsule({
strategy: new LocalStorageStrategy(),
namespace: 'engage'
});
await capsule.setItem('shahata', 123);
console.log(await capsule.getItem('shahata')); // logs 123
How to use it
import {DataCapsule, LocalStorageStrategy} from 'data-capsule';
import secs from 'secs';
const capsule = new DataCapsule({
strategy: new LocalStorageStrategy(),
scope: {userId, siteId}, //optional
namespace: 'engage' //required
});
await capsule.setItem('shahata', 123, {
expiration: secs('2 days') //optional
});
console.log(await capsule.getItem('shahata')); // logs 123
Scope & Expiration
class BaseStrategy {
setItem(key, value, {namespace, scope, expiration})
getItem(key, {namespace, scope})
removeItem(key, {namespace, scope})
getAllItems({namespace, scope})
}
Strategies
class DataCapsule {
constructor({strategy, namespace, scope})
setItem(key, value, {namespace, scope, expiration})
getItem(key, {namespace, scope})
removeItem(key, {namespace, scope})
getAllItems({namespace, scope})
}
Local Storage Strategy
const capsule = new DataCapsule({
strategy: new LocalStorageStrategy()
});
- Manages expiration
- Auto cleans on quota exceeded
- Maintains LRU
- Consistent namespace & scope handling
Wix Storage Strategy
const capsule = new DataCapsule({
strategy: new WixStorageStrategy()
});
- Saves to remote DB using user preferences service
- Scope are automatically per user, can be optionally per site
- Expiration is rounded to days
Cached Storage Strategy
const capsule = new DataCapsule({
strategy: new CachedStorageStrategy({
remoteStrategy: new WixStorageStrategy(),
localStrategy: new LocalStorageStrategy()
})
});
- Every value you get from server is cached locally (even if not found)
- Every time you set or remove, it is cached locally
- Expiration of local cache is up to 1 hour so it won't become stale
Frame Storage Strategy
const capsule = new DataCapsule({
strategy: new FrameStorageStrategy(window.top, '*', 'secret'))
});
- Commands are sent with postMessage to top window
- Listener can get strategy in constructor (default is LocalStorageStrategy)
- Listener can authenticate using callback
import {FrameStorageListener} from 'data-capsule';
const listener = new FrameStorageListener();
listener.start((source, origin, token) => token === 'secret');
//...
listener.stop();
Write your own strategy!
- IndexDBStrategy
- InMemoryStrategy
- EncryptedStrategy
- PigeonPostStrategy
Use it!
- https://github.com/wix/data-capsule
- Published to npm & bower
- Can be used both in new and old stack
- Test coverage 100%
- Open source
Incidental open source
- https://github.com/wix/greedy-split
- https://github.com/wix/describe-jsdom
- https://github.com/wix/secs
Questions???
Data Capsule
By Shahar Talmi
Data Capsule
- 1,693