Fixed offline injection and added Error support
This commit is contained in:
parent
1679782085
commit
2010e420d8
|
@ -77,7 +77,7 @@ A javascript library providing server defined loading of assets for a single pag
|
||||||
* debug.handler = Prints/log debug message. (default: console.log)
|
* debug.handler = Prints/log debug message. (default: console.log)
|
||||||
* debug.prefix = Debug message prefix. (default: 'FFSpaLoader.')
|
* debug.prefix = Debug message prefix. (default: 'FFSpaLoader.')
|
||||||
* error.handler = The error handler. (default: internal error handler ui)
|
* error.handler = The error handler. (default: internal error handler ui)
|
||||||
* error.title = The error title. (default: 'Loader Error');
|
* error.title = The error title. (default: 'Loader ');
|
||||||
* error.style = The error ui css style. (default: red border box)
|
* error.style = The error ui css style. (default: red border box)
|
||||||
* boot.cordova.enable = Use deviceready event to boot when cordova is detected. (default: true)
|
* boot.cordova.enable = Use deviceready event to boot when cordova is detected. (default: true)
|
||||||
* boot.cordova.timeout = Boot after (if<0=no-)timeout when deviceready event is not received. (default: -1)
|
* boot.cordova.timeout = Boot after (if<0=no-)timeout when deviceready event is not received. (default: -1)
|
||||||
|
@ -143,6 +143,7 @@ A javascript library providing server defined loading of assets for a single pag
|
||||||
* Chromium 46
|
* Chromium 46
|
||||||
* Iceweasel 43
|
* Iceweasel 43
|
||||||
* Opera 12 Presto
|
* Opera 12 Presto
|
||||||
|
* IE 11 Edge
|
||||||
* Android 5 in Cordova
|
* Android 5 in Cordova
|
||||||
|
|
||||||
## Todo
|
## Todo
|
||||||
|
@ -167,6 +168,7 @@ Add unit tests for any new or changed functionality. Lint and test your code.
|
||||||
### 0.0.4
|
### 0.0.4
|
||||||
* Disable cordova timeout per default.
|
* Disable cordova timeout per default.
|
||||||
* Remove unused mobileAgent detect.
|
* Remove unused mobileAgent detect.
|
||||||
|
* Fixed cached resources loading.
|
||||||
|
|
||||||
|
|
||||||
### 0.0.3
|
### 0.0.3
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
handler: null, // auto filled
|
handler: null, // auto filled
|
||||||
title: 'Loader Error',
|
title: 'Loader ',
|
||||||
style: '.ffError { margin: auto;width: 90%;border: 3px solid red;padding-left: 1em;padding-bottom: 1em;}'
|
style: '.ffError { margin: auto;width: 90%;border: 3px solid red;padding-left: 1em;padding-bottom: 1em;}'
|
||||||
},
|
},
|
||||||
boot: {
|
boot: {
|
||||||
|
@ -158,20 +158,20 @@
|
||||||
cb(null);
|
cb(null);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
var sqlErrorHandler = function(cb) {
|
var executeSql = function(tx, query, values, resultHandler, errorHandler) {
|
||||||
return function (tx, err) {
|
tx.executeSql(query, values, resultHandler, function(tx,err) {
|
||||||
cb(err.message+' code: '+err.code);
|
errorHandler(new Error('Code: '+err.code+' '+err.message+' by query: '+query));
|
||||||
};
|
});
|
||||||
};
|
};
|
||||||
var cacheDBInit = function(cb) {
|
var cacheDBInit = function(cb) {
|
||||||
cacheDB.transaction(function(tx) {
|
cacheDB.transaction(function(tx) {
|
||||||
var query = 'CREATE TABLE cache_store(id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, value TEXT NOT NULL)';
|
var query = 'CREATE TABLE cache_store(id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, value TEXT NOT NULL)';
|
||||||
utilDebug('websql.init query '+query);
|
utilDebug('websql.init query '+query);
|
||||||
tx.executeSql(query, [], function(tx) {
|
executeSql(tx, query, [], function(tx) {
|
||||||
var query = 'CREATE UNIQUE INDEX cache_store__key__udx ON cache_store (key)';
|
var query = 'CREATE UNIQUE INDEX cache_store__key__udx ON cache_store (key)';
|
||||||
utilDebug('websql.init query '+query);
|
utilDebug('websql.init query '+query);
|
||||||
tx.executeSql(query, [], function() {cb(null);}, sqlErrorHandler(cb));
|
executeSql(tx, query, [], nullDataHandler(cb), cb);
|
||||||
}, sqlErrorHandler(cb));
|
}, cb);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
|
@ -187,7 +187,7 @@
|
||||||
cacheDB.transaction(function(tx) {
|
cacheDB.transaction(function(tx) {
|
||||||
var query = 'SELECT value FROM cache_store WHERE key = \"test-for-table\"';
|
var query = 'SELECT value FROM cache_store WHERE key = \"test-for-table\"';
|
||||||
utilDebug('websql.cacheOpen query '+query);
|
utilDebug('websql.cacheOpen query '+query);
|
||||||
tx.executeSql(query, [], function() {
|
executeSql(tx, query, [], function() {
|
||||||
cb(null);
|
cb(null);
|
||||||
}, function() {
|
}, function() {
|
||||||
cacheDBInit(cb);
|
cacheDBInit(cb);
|
||||||
|
@ -198,40 +198,40 @@
|
||||||
cacheDB.transaction(function(tx) {
|
cacheDB.transaction(function(tx) {
|
||||||
var query = 'SELECT value FROM cache_store WHERE key = ?';
|
var query = 'SELECT value FROM cache_store WHERE key = ?';
|
||||||
utilDebug('websql.cacheGetValue query '+query);
|
utilDebug('websql.cacheGetValue query '+query);
|
||||||
tx.executeSql(query,[key], function(tx, res) {
|
executeSql(tx, query,[key], function(tx, res) {
|
||||||
if (res.rows.length === 0) {
|
if (res.rows.length === 0) {
|
||||||
cb(null, null);
|
cb(null, null);
|
||||||
} else {
|
} else {
|
||||||
var value = res.rows.item(0).value;
|
var value = res.rows.item(0).value;
|
||||||
cb(null, JSON.parse(value));
|
cb(null, JSON.parse(value));
|
||||||
}
|
}
|
||||||
}, sqlErrorHandler(cb));
|
}, cb);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
cacheSetValue: function(key, value, cb) {
|
cacheSetValue: function(key, value, cb) {
|
||||||
cacheDB.transaction(function(tx) {
|
cacheDB.transaction(function(tx) {
|
||||||
var query = 'SELECT value FROM cache_store WHERE key = ?';
|
var query = 'SELECT value FROM cache_store WHERE key = ?';
|
||||||
utilDebug('websql.cacheSetValue query '+query);
|
utilDebug('websql.cacheSetValue query '+query);
|
||||||
tx.executeSql(query,[key], function(tx, res) {
|
executeSql(tx, query,[key], function(tx, res) {
|
||||||
if (res.rows.length === 0) {
|
if (res.rows.length === 0) {
|
||||||
var queryInsert = 'INSERT INTO cache_store (key,value) VALUES (?,?)';
|
var queryInsert = 'INSERT INTO cache_store (key,value) VALUES (?,?)';
|
||||||
utilDebug('websql.cacheSetValue query '+queryInsert);
|
utilDebug('websql.cacheSetValue query '+queryInsert);
|
||||||
tx.executeSql(queryInsert, [key,JSON.stringify(value)], nullDataHandler(cb), sqlErrorHandler(cb));
|
executeSql(tx, queryInsert, [key,JSON.stringify(value)], nullDataHandler(cb), cb);
|
||||||
} else {
|
} else {
|
||||||
var queryUpdate = 'UPDATE cache_store SET value = ? WHERE key = ?';
|
var queryUpdate = 'UPDATE cache_store SET value = ? WHERE key = ?';
|
||||||
utilDebug('websql.cacheSetValue query '+queryUpdate);
|
utilDebug('websql.cacheSetValue query '+queryUpdate);
|
||||||
tx.executeSql(queryUpdate, [JSON.stringify(value),key], nullDataHandler(cb), sqlErrorHandler(cb));
|
executeSql(tx, queryUpdate, [JSON.stringify(value),key], nullDataHandler(cb), cb);
|
||||||
}
|
}
|
||||||
}, sqlErrorHandler(cb));
|
}, cb);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
cacheDeleteValue: function(key, cb) {
|
cacheDeleteValue: function(key, cb) {
|
||||||
cacheDB.transaction(function(tx) {
|
cacheDB.transaction(function(tx) {
|
||||||
var query = 'DELETE FROM cache_store WHERE key = ?';
|
var query = 'DELETE FROM cache_store WHERE key = ?';
|
||||||
utilDebug('websql.cacheDeleteValue query '+query);
|
utilDebug('websql.cacheDeleteValue query '+query);
|
||||||
tx.executeSql(query, [key], function () {
|
executeSql(tx, query, [key], function () {
|
||||||
setTimeout(function() {cb(null);}); // return next tick so transaction is flushed before location.reload
|
setTimeout(nullDataHandler(cb)); // return next tick so transaction is flushed before location.reload
|
||||||
}, sqlErrorHandler(cb));
|
}, cb);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -257,10 +257,14 @@
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
var utilErrorHandler = function(err) {
|
var utilErrorHandler = function(err) {
|
||||||
utilDebug('utilErrorHandler error '+err); // TODO: Add Error object support
|
if (!(err instanceof Error)) {
|
||||||
|
err = new Error(err);
|
||||||
|
}
|
||||||
|
utilDebug('utilErrorHandler error '+err.name+' '+err.message);
|
||||||
|
|
||||||
var rootTag = document.createElement('div');
|
var rootTag = document.createElement('div');
|
||||||
rootTag.setAttribute('class','ffError');
|
rootTag.setAttribute('class','ffError');
|
||||||
|
document.getElementsByTagName('body')[0].appendChild(rootTag);
|
||||||
|
|
||||||
var cssTag = document.createElement('style');
|
var cssTag = document.createElement('style');
|
||||||
cssTag.type = 'text/css';
|
cssTag.type = 'text/css';
|
||||||
|
@ -268,14 +272,24 @@
|
||||||
rootTag.appendChild(cssTag);
|
rootTag.appendChild(cssTag);
|
||||||
|
|
||||||
var titleTag = document.createElement('h1');
|
var titleTag = document.createElement('h1');
|
||||||
titleTag.appendChild(document.createTextNode(options.error.title));
|
titleTag.appendChild(document.createTextNode(options.error.title+err.name));
|
||||||
rootTag.appendChild(titleTag);
|
rootTag.appendChild(titleTag);
|
||||||
|
|
||||||
var questionTag = document.createElement('p');
|
var questionTag = document.createElement('p');
|
||||||
questionTag.appendChild(document.createTextNode(err));
|
questionTag.appendChild(document.createTextNode(err.message));
|
||||||
rootTag.appendChild(questionTag);
|
rootTag.appendChild(questionTag);
|
||||||
|
|
||||||
document.getElementsByTagName('body')[0].appendChild(rootTag);
|
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 traceTag = document.createElement('div');
|
||||||
|
traceTag.appendChild(document.createTextNode(stackText));
|
||||||
|
rootTag.appendChild(traceTag);
|
||||||
|
} catch (stackError) {
|
||||||
|
utilDebug('No stack: '+stackError);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -315,7 +329,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
var cacheCheckType = function (type, cb, action) {
|
var cacheCheckType = function (type, cb, action) {
|
||||||
cacheHasService(type)?action():cb('No caching for '+type);
|
cacheHasService(type)?action():cb(new Error('No caching for '+type));
|
||||||
};
|
};
|
||||||
|
|
||||||
var cacheGetValue = function(type, key , cb) {
|
var cacheGetValue = function(type, key , cb) {
|
||||||
|
@ -450,33 +464,27 @@
|
||||||
loadResource(resourceStack[0],resourceLoader);
|
loadResource(resourceStack[0],resourceLoader);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var injectResource = function(resource, cb) {
|
||||||
|
cacheGetValue(resource.type,resource.hash,function(err,item) {
|
||||||
|
injectResourceData(resource,item.data,cb);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var injectResources = function(resources, cb) {
|
var injectResources = function(resources, cb) {
|
||||||
var startTime = new Date().getTime();
|
var startTime = new Date().getTime();
|
||||||
utilDebug('injectResources');
|
utilDebug('injectResources');
|
||||||
resources.forEach(function (resource) {
|
var resourceStack = resources;
|
||||||
cacheGetValue(resource.type,resource.hash,function(err,item) {
|
var resourceLoader = function(err) {
|
||||||
// TODO reuse injectResourceData
|
if (err !== null) { return cb(err); }
|
||||||
|
resourceStack = resourceStack.slice(1);
|
||||||
var tag = null;
|
if (resourceStack.length === 0) {
|
||||||
if (resource.type === 'css' || resource.type === 'cssData') {
|
utilDebug('injectResources done in '+(new Date().getTime()-startTime)+' ms.');
|
||||||
tag = document.createElement('style');
|
cb(null);
|
||||||
tag.type = 'text/css';
|
} else {
|
||||||
}
|
injectResource(resourceStack[0],resourceLoader);
|
||||||
if (resource.type === 'js') {
|
}
|
||||||
tag = document.createElement('script');
|
};
|
||||||
tag.type = 'text/javascript';
|
injectResource(resourceStack[0],resourceLoader);
|
||||||
}
|
|
||||||
utilDebug('injectResources from '+JSON.stringify(resource));
|
|
||||||
|
|
||||||
tag.appendChild(document.createTextNode(item.data));
|
|
||||||
|
|
||||||
//document.getElementsByTagName('head')[0].appendChild(tag);
|
|
||||||
var ref = document.getElementsByTagName('script')[0];
|
|
||||||
ref.parentNode.insertBefore(tag, ref); // note in reverse order
|
|
||||||
});
|
|
||||||
});
|
|
||||||
utilDebug('injectResources done in '+(new Date().getTime()-startTime)+' ms.');
|
|
||||||
cb(null); // FIXME async
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -488,11 +496,11 @@
|
||||||
*/
|
*/
|
||||||
var startLoader = function (cb) {
|
var startLoader = function (cb) {
|
||||||
if (options.server.url === null) {
|
if (options.server.url === null) {
|
||||||
cb('Missing options.server.url');
|
cb(new Error('No url'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.server.assets === null) {
|
if (options.server.assets === null) {
|
||||||
cb('Missing options.server.assets');
|
cb(new Error('No assets'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rootWindow[options.server.flag] = options.server.url;
|
rootWindow[options.server.flag] = options.server.url;
|
||||||
|
@ -507,13 +515,13 @@
|
||||||
if (err !== null) {
|
if (err !== null) {
|
||||||
cb(err);
|
cb(err);
|
||||||
} else if (value === null) {
|
} else if (value === null) {
|
||||||
cb('Have no cache of server resouces from '+options.server.url);
|
cb(new Error('Have no cache of server resouces from '+options.server.url));
|
||||||
} else {
|
} else {
|
||||||
injectResources(value, cb);
|
injectResources(value, cb);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cb('Could not fetch server resouces from '+options.server.url);
|
cb(new Error('Could not fetch server resouces from '+options.server.url));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ var morgan = require('morgan');
|
||||||
|
|
||||||
// example options;
|
// example options;
|
||||||
var serverUrl = 'http://localhost:8080';
|
var serverUrl = 'http://localhost:8080';
|
||||||
var useInline = true; // or false
|
var useInline = false; // or false
|
||||||
|
|
||||||
var clientResourcesWeb = [];
|
var clientResourcesWeb = [];
|
||||||
var clientResources = {
|
var clientResources = {
|
||||||
|
@ -123,7 +123,11 @@ server.use('/static/module/angular', express.static(path.join(__dirname,'n
|
||||||
server.use('/static/module/angular-route', express.static(path.join(__dirname,'node_modules/angular-route')));
|
server.use('/static/module/angular-route', express.static(path.join(__dirname,'node_modules/angular-route')));
|
||||||
|
|
||||||
server.get('/static/es5-ff-spa-loader.js', function (req,res) {
|
server.get('/static/es5-ff-spa-loader.js', function (req,res) {
|
||||||
res.write(fs.readFileSync(__dirname+'/../dist/es5-ff-spa-loader.js', 'utf8'));
|
if (fs.existsSync(__dirname+'/../es5-ff-spa-loader.js')) {
|
||||||
|
res.write(fs.readFileSync(__dirname+'/../es5-ff-spa-loader.js', 'utf8'));
|
||||||
|
} else {
|
||||||
|
res.write(fs.readFileSync(__dirname+'/../dist/es5-ff-spa-loader.js', 'utf8'));
|
||||||
|
}
|
||||||
res.end();
|
res.end();
|
||||||
});
|
});
|
||||||
server.get('/static/spa-client-resources', function (req,res) {
|
server.get('/static/spa-client-resources', function (req,res) {
|
||||||
|
|
Loading…
Reference in a new issue