reworked localStorage/sessionStorage store backend, still not content with the HL API...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2018-02-18 15:02:45 +03:00
parent dacdb01bbe
commit 2f14d723b2
5 changed files with 117 additions and 134 deletions

View File

@ -113,8 +113,8 @@ module.ConfigStore = core.ImageGridFeatures.Feature({
// XXX need to update rather than rewrite things... // XXX need to update rather than rewrite things...
['prepareStoreToSave', ['prepareStoreToSave',
function(res){ function(res){
//var ls_path = '/${ROOT_PATH}/config' var ls_path = '${INSTANCE}/config'
var ls_path = 'config' //var ls_path = 'config'
// localStorage... // localStorage...
// NOTE: we do not need to clone anything here as this // NOTE: we do not need to clone anything here as this
@ -135,8 +135,7 @@ module.ConfigStore = core.ImageGridFeatures.Feature({
['storeDataLoaded', ['storeDataLoaded',
function(data){ function(data){
var base = this.__base_config = this.__base_config || this.config var base = this.__base_config = this.__base_config || this.config
//var ls_path = '/${ROOT_PATH}/config' var ls_path = '${INSTANCE}/config'
var ls_path = 'config'
// XXX sort out load priority/logic... // XXX sort out load priority/logic...
// - one or the other or both? // - one or the other or both?

View File

@ -670,6 +670,8 @@ var CacheActions = actions.Actions({
NOTE: both "modes" of doing a pre-cache run in the main thread, NOTE: both "modes" of doing a pre-cache run in the main thread,
the difference is that the "async" version lets JS run frames the difference is that the "async" version lets JS run frames
between processing sync chunks... between processing sync chunks...
NOTE: this will not drop the existing cache, to do this run
.clearCache() first or run .reCache(..).
`, `,
function(t){ function(t){
if(this.config.cache){ if(this.config.cache){
@ -719,6 +721,13 @@ var CacheActions = actions.Actions({
delete this.__cache delete this.__cache
} }
}], }],
// XXX do we need this...
reCache: ['System/Re-cache',
function(t){
this
.clearCache()
.preCache(t) }],
}) })
var Cache = var Cache =

View File

@ -84,7 +84,7 @@ var StoreActions = actions.Actions({
})], })],
// XXX do we need to parse date here??? // base API...
parseStoreQuery: ['- Store/', parseStoreQuery: ['- Store/',
core.doc` core.doc`
@ -145,7 +145,6 @@ var StoreActions = actions.Actions({
} }
}], }],
// base API...
prepareStoreToSave: ['- Store/', prepareStoreToSave: ['- Store/',
core.doc` core.doc`
@ -328,140 +327,116 @@ module.Store = core.ImageGridFeatures.Feature({
// NOTE: the doc is reused for both localStorage and sessionStorage with // NOTE: the doc is reused for both localStorage and sessionStorage with
// appropriate automated changes... // appropriate automated changes...
// XXX Q: do we save to ROOT_PATH by default???
var __storageHandler_doc = var __storageHandler_doc =
core.doc`Handle localStorage store data... core.doc`Handle localStorage store data...
Get localStorage data... Write data to key...
.localStorageDataHandler(key, data)
Get data from key...
.localStorageDataHandler(key)
-> value
Remove key...
.localStorageDataHandler(key, null)
.localStorageDataHandler([key, ..], null)
Get stored keys...
.localStorageDataHandler('?')
-> keys
.localStorageDataHandler() .localStorageDataHandler()
.localStorageDataHandler('??')
-> data -> data
Save data set to localStorage... .localStorageDataHandler([key, ..], '??')
-> data
Expand data to store...
.localStorageDataHandler(data) .localStorageDataHandler(data)
-> this
Save data to key in localStorage... Remove all data...
.localStorageDataHandler(data, key)
-> this
Delete all data from localStorage...
.localStorageDataHandler(null) .localStorageDataHandler(null)
-> this
NOTE: load resolves to the same keys as were passed to load, while NOTE: when handling key expansion the unexpanded key should be used
localStorage stores the expanded keys... to access data, e.g. if writing '\${INSTANCE}/xyz' the same string
'/$\{ROOT_PATH}/path' is returned via .localStorageDataHandler('??') and should be used
--(store)--> this.config['store-root-key'] +'/path' to get the value, i.e.
--(load)--> '/$\{ROOT_PATH}/path' .localStorageDataHandler('\${INSTANCE}/xyz')
Root keys of data partially support path syntax:
'/key' or '../key'
stored in localStorage[key]
'./key' or 'key'
stored as-is in localStorage[this.config['store-root-key']]
Path variables:
$\{ROOT_PATH} - resolves to .config['store-root-key']
NOTE: './key' and $\{ROOT_PATH}/key are
not the same, the former will be stored in:
localStorage[this.config['store-root-key']][key]
while the later is stored in:
localStorage[this.config['store-root-key/' + key]
XXX not yet sure this is the right way to go...
HOTE: other path syntax is ignored and the key will be saved as-is.
` `
function makeStorageHandler(storage, alias){ function makeStorageHandler(storage){
var func = function(data, key){ var func = function(a, b){
alias = alias || storage
storage = typeof(storage) == typeof('str') ? window[storage] : storage storage = typeof(storage) == typeof('str') ? window[storage] : storage
var root_pattern = /^(\.\.)?[\\\/]/ var instance = this.config['store-instance-key']
var root = this.config['store-root-key']
var resolvePath = function(p){ var resolvePath = function(p){
return p return p
.replace('${ROOT_PATH}', root) .replace('${INSTANCE}', instance)
.replace(root_pattern, '') } }
// clear... // XXX should this be all keys by default???
if(data === null){ var keys = Object.keys(storage)
// remove specific key...
if(key){
var data = func.call(this)
data[key] = undefined
func.call(this, data)
// clear all... var dict_key = '${INSTANCE}/__dict__'
} else { var k = resolvePath(dict_key)
var d = storage[root] var dict = JSON.parse(storage[k] || '{}')
d = d != undefined ? JSON.parse(d) : {} dict[k] = dict_key
;(d.__root_paths__ || [])
.forEach(function(p){ // get list of keys...
var key = resolvePath(p) if(a == '?'){
return keys
.map(function(key){ return dict[key] || key })
// get store contents...
} else if(a == '??'
|| arguments.length == 0
|| (a instanceof Array && (b == '??' || arguments.length == 1))){
var res = {}
var keys = a instanceof Array ? a : keys
keys.forEach(function(key){
res[dict[key] || key] = JSON.parse(storage[key]) })
return res
// remove all keys...
} else if(a === null || (a instanceof Array && b === null)){
;(a || keys)
.forEach(function(key){
delete storage[key] }) delete storage[key] })
delete storage[root] dict = {}
}
// set... // expand data to store...
// NOTE: this will update existing data set... } else if(typeof(a) != typeof('str')){
// NOTE: attrs explicitly set to undefined are removed... Object.keys(a).forEach(function(key){
} else if(data){ var k = resolvePath(key)
if(key){ k != key
data = { [key]: data } && (dict[k] = key)
} storage[k] = JSON.stringify(a[key]) })
// update existing data... // remove key...
var old = func.call(this) } else if(b === null){
Object.keys(data).forEach(function(k){ var k = resolvePath(a)
if(data[k] === undefined){ delete dict[k]
delete old[k] delete storage[k]
delete data[k]
}
})
data = Object.assign(old, data)
var root_data = {} // get key...
var root_paths = [] } else if(b === undefined){
var k = resolvePath(a)
return k in storage ?
JSON.parse(storage[k])
: actions.UNDEFINED
// handle root paths... // write key...
Object.keys(data)
.forEach(function(p){
if(root_pattern.test(p)){
var key = resolvePath(p)
root_paths.push(p)
root_data[key] = JSON.stringify(data[p])
delete data[p]
}
})
data.__root_paths__ = root_paths
storage[root] = JSON.stringify(data)
// store root stuff...
Object.assign(storage, root_data)
// get...
} else { } else {
var d = storage[root] var k = resolvePath(a)
d = d != undefined ? JSON.parse(d) : {} k != a
&& (dict[k] = a)
// load root paths... storage[k] = JSON.stringify(b)
;(d.__root_paths__ || [])
.forEach(function(p){
var key = resolvePath(p)
var o = storage[key]
o = o != undefined ? JSON.parse(o) : o
d[p] = o
})
delete d.__root_paths__
return d
} }
storage[resolvePath('${INSTANCE}/__dict__')] = JSON.stringify(dict)
} }
if(typeof(storage) == typeof('str')){ if(typeof(storage) == typeof('str')){
@ -478,16 +453,16 @@ function makeStorageHandler(storage, alias){
// load the store... (???) // load the store... (???)
var StoreLocalStorageActions = actions.Actions({ var StoreLocalStorageActions = actions.Actions({
config: { config: {
'store-root-key': 'ImageGrid.Viewer.main', 'store-instance-key': 'ImageGrid.Viewer.main',
}, },
// NOTE: for docs see __storageHandler_doc... // NOTE: for docs see __storageHandler_doc...
localStorageDataHandler: ['- Store/', localStorageDataHandler: ['- Store/',
{handle_data_store: 'storage',}, {handle_data_store: 'storage',},
makeStorageHandler('localStorage', 'storage')], makeStorageHandler('localStorage')],
sessionStorageDataHandler: ['- Store/', sessionStorageDataHandler: ['- Store/',
{handle_data_store: 'session',}, {handle_data_store: 'session',},
makeStorageHandler('sessionStorage', 'session')], makeStorageHandler('sessionStorage')],
}) })
var StoreLocalStorage = var StoreLocalStorage =

View File

@ -1058,9 +1058,9 @@
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
}, },
"ig-actions": { "ig-actions": {
"version": "3.16.0", "version": "3.18.0",
"resolved": "https://registry.npmjs.org/ig-actions/-/ig-actions-3.16.0.tgz", "resolved": "https://registry.npmjs.org/ig-actions/-/ig-actions-3.18.0.tgz",
"integrity": "sha512-4ibmH2vMNYxzac63ibCS5vwSr6C+NO+IJLwft9eEorAxyi74es+QRgyPPyZVqHOB9GouUZM9kWQVDxcZYrGp+w==", "integrity": "sha512-wiN7pjt5CfklD/XNiehJnxrAn6/K7/dorUAYG0zTItYTCtp3iqyPCDtFiAF/PAFMbWjbiQxA2w8oIrZNV1QECQ==",
"requires": { "requires": {
"ig-object": "1.0.2" "ig-object": "1.0.2"
} }
@ -1070,7 +1070,7 @@
"resolved": "https://registry.npmjs.org/ig-features/-/ig-features-3.3.4.tgz", "resolved": "https://registry.npmjs.org/ig-features/-/ig-features-3.3.4.tgz",
"integrity": "sha512-nJmMDfY6JiyQ2mQj31oMOmw/HOY4zbN6yyPEFu61ySXU/f3+CC/GZjdaYFemVbnZThC7hcxYfmj62eSjt7oT+Q==", "integrity": "sha512-nJmMDfY6JiyQ2mQj31oMOmw/HOY4zbN6yyPEFu61ySXU/f3+CC/GZjdaYFemVbnZThC7hcxYfmj62eSjt7oT+Q==",
"requires": { "requires": {
"ig-actions": "3.16.0", "ig-actions": "3.18.0",
"ig-object": "1.0.2" "ig-object": "1.0.2"
} }
}, },

View File

@ -26,7 +26,7 @@
"fs-walk": "^0.0.1", "fs-walk": "^0.0.1",
"glob": "^4.0.6", "glob": "^4.0.6",
"guarantee-events": "^1.0.0", "guarantee-events": "^1.0.0",
"ig-actions": "^3.16.0", "ig-actions": "^3.18.0",
"ig-features": "^3.3.4", "ig-features": "^3.3.4",
"ig-object": "^1.0.2", "ig-object": "^1.0.2",
"moment": "^2.20.1", "moment": "^2.20.1",