diff --git a/README.md b/README.md index 0a36384..1b9ea73 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ A javascript library providing server defined loading of assets for a single pag * server.question.title = The question ui title. (default: 'Server') * server.question.text = The question ui text. (default: 'Please provide the server name;') * server.question.style = The question ui css style.(note: pending change) (default: green border box) - * cache.meta = The cache backend for the meta information, null is auto select. (default: null) + * cache.meta = The cache backend for the meta information(server.url+content), null is auto select. (default: null) * cache.js = The cache backend for for js, null is auto select. (default: null) * cache.css = The cache backend for for css, null is auto select. (default: null) * cache.cssData = The cache backend for for cssData, null is auto select. (default: null) @@ -121,7 +121,7 @@ A javascript library providing server defined loading of assets for a single pag More custom schemas are possible like; (todo: needs testing) - FFSpaLoader.options.cache.meta = null; // use auto -> TODO: currently other cached need meta needs fixing. + FFSpaLoader.options.cache.meta = false; FFSpaLoader.options.cache.js = false; FFSpaLoader.options.cache.css = false; FFSpaLoader.options.cache.cssData = false; @@ -148,7 +148,6 @@ A javascript library providing server defined loading of assets for a single pag ## Todo - * Auto cache cleanup code. (!! required before production !!) * test in production * Server header set+check support * Redo css(?divs) of server question @@ -166,9 +165,10 @@ Add unit tests for any new or changed functionality. Lint and test your code. ## Release History ### 0.0.4 +* Added auto cache clean code * Disable cordova timeout per default. * Remove unused mobileAgent detect. -* Fixed cached resources loading. +* Fixed cached resources injection order. ### 0.0.3 diff --git a/es5-ff-spa-loader.js b/es5-ff-spa-loader.js index 9a77688..e54f6e8 100644 --- a/es5-ff-spa-loader.js +++ b/es5-ff-spa-loader.js @@ -159,6 +159,7 @@ }; }; var executeSql = function(tx, query, values, resultHandler, errorHandler) { + utilDebug('websql.executeSql '+query); tx.executeSql(query, values, resultHandler, function(tx,err) { errorHandler(new Error('Code: '+err.code+' '+err.message+' by query: '+query)); }); @@ -166,11 +167,8 @@ var cacheDBInit = function(cb) { cacheDB.transaction(function(tx) { var query = 'CREATE TABLE cache_store(id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, value TEXT NOT NULL)'; - utilDebug('websql.init query '+query); executeSql(tx, query, [], function(tx) { - var query = 'CREATE UNIQUE INDEX cache_store__key__udx ON cache_store (key)'; - utilDebug('websql.init query '+query); - executeSql(tx, query, [], nullDataHandler(cb), cb); + executeSql(tx, 'CREATE UNIQUE INDEX cache_store__key__udx ON cache_store (key)', [], nullDataHandler(cb), cb); }, cb); }); }; @@ -185,9 +183,7 @@ return cb(e); } cacheDB.transaction(function(tx) { - var query = 'SELECT value FROM cache_store WHERE key = \"test-for-table\"'; - utilDebug('websql.cacheOpen query '+query); - executeSql(tx, query, [], function() { + executeSql(tx,'SELECT value FROM cache_store WHERE key = \"test-for-table\"', [], function() { cb(null); }, function() { cacheDBInit(cb); @@ -196,9 +192,7 @@ }, cacheGetValue: function(key, cb) { cacheDB.transaction(function(tx) { - var query = 'SELECT value FROM cache_store WHERE key = ?'; - utilDebug('websql.cacheGetValue query '+query); - executeSql(tx, query,[key], function(tx, res) { + executeSql(tx, 'SELECT value FROM cache_store WHERE key = ?',[key], function(tx, res) { if (res.rows.length === 0) { cb(null, null); } else { @@ -210,16 +204,12 @@ }, cacheSetValue: function(key, value, cb) { cacheDB.transaction(function(tx) { - var query = 'SELECT value FROM cache_store WHERE key = ?'; - utilDebug('websql.cacheSetValue query '+query); - executeSql(tx, query,[key], function(tx, res) { + executeSql(tx, 'SELECT value FROM cache_store WHERE key = ?',[key], function(tx, res) { if (res.rows.length === 0) { var queryInsert = 'INSERT INTO cache_store (key,value) VALUES (?,?)'; - utilDebug('websql.cacheSetValue query '+queryInsert); executeSql(tx, queryInsert, [key,JSON.stringify(value)], nullDataHandler(cb), cb); } else { var queryUpdate = 'UPDATE cache_store SET value = ? WHERE key = ?'; - utilDebug('websql.cacheSetValue query '+queryUpdate); executeSql(tx, queryUpdate, [JSON.stringify(value),key], nullDataHandler(cb), cb); } }, cb); @@ -227,9 +217,7 @@ }, cacheDeleteValue: function(key, cb) { cacheDB.transaction(function(tx) { - var query = 'DELETE FROM cache_store WHERE key = ?'; - utilDebug('websql.cacheDeleteValue query '+query); - executeSql(tx, query, [key], function () { + executeSql(tx, 'DELETE FROM cache_store WHERE key = ?', [key], function () { setTimeout(nullDataHandler(cb)); // return next tick so transaction is flushed before location.reload }, cb); }); @@ -282,7 +270,7 @@ try { var stack = err.stack || ''; stack = stack.split('\n').map(function (line) { return line.trim(); }); - var stackText = stack.splice(stack[0] == 'Error' ? 2 : 1); + var stackText = stack.splice(stack[0] === 'Error' ? 2 : 1); var traceTag = document.createElement('div'); traceTag.appendChild(document.createTextNode(stackText)); @@ -316,6 +304,26 @@ }; httpRequest.send(); }; + + var utilRunStack = function(runType, stack, step, cb) { + if (stack.length === 0) { + return cb(null); + } + utilDebug(runType); + var startTime = new Date().getTime(); + var runStack = stack; + var runStackStep = function(err) { + if (err !== null) { return cb(err); } + runStack = runStack.slice(1); + if (runStack.length === 0) { + utilDebug(runType+' done '+stack.length+' in '+(new Date().getTime()-startTime)+' ms.'); + cb(null); + } else { + step(runStack[0],runStackStep); + } + }; + step(runStack[0],runStackStep); + }; var cacheGetService = function (type) { if (options.cache[type]) { @@ -356,11 +364,64 @@ }); }; -// var cleanupCache = function (resources, cb) { -// utilDebug('cleanupCache TODO cacheList '+0+' resources '+resources.length); -// // TODO: impl for removes in resource lists -// cb(null); -// }; + var cleanupCache = function (resources, cb) { + var typedKeys = {}; + resources.forEach(function (r) { + var typeKey = typedKeys[r.type]; + if (typeKey === undefined) { + typeKey = []; + typedKeys[r.type] = typeKey; + } + typeKey.push(r.hash); + }); + var steps = []; + var keys = Object.keys(typedKeys); + for (var keyIdx in keys) { + var type = keys[keyIdx]; + if (!cacheHasService(type)) { + continue; + } + steps.push({keys: typedKeys[type], type: type}); + } + utilRunStack('cleanupCacheKeys',steps, function(typeKey, cb) { + cacheGetValue(typeKey.type,'keys',function (err,value) { + if (err !== null) { + return cb(err); + } + if (value === null) { + return cb(null); + } + var diff = []; + for (var i=0;i