cache of localStorage for quicker access
map of dirty objects by their ids
queue of method calls done during bootstrapping
extend this property with extra functions that will be available on all promises returned by hoodie.store API. It has a reference to current hoodie instance by default
if browser does not support local storage persistence, e.g. Safari in private mode, overite the respective methods.
2 seconds timout before triggering the store:idle event
localStorage proxy
saves the passed object into the store and replaces an eventually existing object with same type & id.
When id is undefined, it gets generated an new object gets saved
It also adds timestamps along the way:
createdAt unless it already existsupdatedAt every time_syncedAt if changes comes from remoteexample usage:
store.save('car', undefined, {color: 'red'})
store.save('car', 'abc4567', {color: 'red'})
if store is currently bootstrapping data from remote, we're queueing until it's finished
make sure we don't mess with the passed object directly
generate an id if necessary
add createdBy hash to new objects
note: we check for hoodie.account as in some cases, the code
might get executed before the account module is initiated.
todo: move ownerHash into a method on the core hoodie module
handle local properties and hidden properties with $ prefix keep local properties for remote updates
for remote updates, keep local properties (starting with '_') for local updates, keep hidden properties (starting with '$')
add timestamps
handle local changes
A local change is meant to be replicated to the users database, but not beyond. For example when I subscribed to a share but then decide to unsubscribe, all objects get removed with local: true flag, so that they get removed from my database, but won't anywhere else.
loads one object from Store, specified by type and id
example usage:
store.find('car', 'abc4567')
if store is currently bootstrapping data from remote, we're queueing until it's finished
returns all objects from store. Can be optionally filtered by a type or a function
example usage:
store.findAll()
store.findAll('car')
store.findAll(function(obj) { return obj.brand == 'Tesla' })
if store is currently bootstrapping data from remote, we're queueing until it's finished
normalize filter
sort from newest to oldest
Removes one object specified by type and id.
when object has been synced before, mark it as deleted. Otherwise remove it from Store.
if store is currently bootstrapping data from remote, we're queueing until it's finished
if change comes from remote, just clean up locally
just decorating returned promises
object key index TODO: make this cachy
loads an object specified by type and id only once from localStorage
and caches it for faster future access. Updates cache when value is passed.
Also checks if object needs to be synched (dirty) or not
Pass options.remote = true when object comes from remote
Pass 'options.silent = true' to avoid events from being triggered.
if the cached key returns false, it means that we have removed that key. We just set it to false for performance reasons, so that we don't need to look it up again in localStorage
if key is cached, return it. But make sure to make a deep copy beforehand (=> true)
if object is not yet cached, load it from localStore
stop here if object did not exist in localStore and cache it so we don't need to look it up again
here is where we cache the object for future quick access
removes an object from the list of objects that are flagged to by synched (dirty)
and triggers a store:dirty event
when an object gets deleted that has been synched before (_rev attribute),
it cannot be removed from store but gets a _deleted: true attribute
Marks object as changed (dirty). Triggers a store:dirty event immediately and a
store:idle event once there is no change within 2 seconds
Marks all local object as changed (dirty) to make them sync with remote
returns an Array of all dirty documents
When no arguments passed, returns true or false depending on if there are
dirty objects in the store.
Otherwise it returns true or false for the passed object. An object is dirty
if it has no _syncedAt attribute or if updatedAt is more recent than _syncedAt
clears localStorage and cache
TODO: do not clear entire localStorage, clear only the items that have been stored
using hoodie.store before.
returns true or false depending on whether localStorage is supported or not.
Beware that some browsers like Safari do not support localStorage in private mode.
inspired by this cappuccino commit https://github.com/cappuccino/cappuccino/commit/063b05d9643c35b303568a28809e4eb3224f71ec
we've to put this in here. I've seen Firefox throwing Security error: 1000
when cookies have been disabled
Just because localStorage exists does not mean it works. In particular it might be disabled as it is when Safari's private browsing mode is active.
that should not happen ...
okay, let's clean up if we got here.
in case of an error, like Safari's Private Pussy, return false
we're good.
proxies to hoodie.trigger
proxies to hoodie.on
proxies to hoodie.unbind
extend promises returned by store.api
returns true if store is currently bootstrapping data from remote, otherwise false.
bootstrapping dirty objects, to make sure that removed objects get pushed after page reload.
subscribe to events coming from account & our remote store.
account events
remote events
when a change come's from our remote store, we differentiate whether an object has been removed or added / updated and reflect the change in our local store.
more advanced localStorage wrappers to find/save objects
store IDs of dirty objects
only lowercase letters, numbers and dashes are allowed for ids
just like ids, but must start with a letter or a $ (internal types)
_hasLocalChanges returns true if there is a local change that
has not been sync'd yet.
this is where all the store events get triggered, like add:task, change:note:abc4567, remove, etc.
when an object gets changed, two special events get triggerd:
dirty event gets triggered immediately, for every
change that happens.idle event gets triggered after a short timeout of
no changes, e.g. 2 seconds.
LocalStore
window.localStrage wrapper and more