mirror of
https://github.com/flyandi/mazda-custom-application-sdk
synced 2024-12-23 03:35:29 -06:00
Reworking resource loader to be completly driven by node-cmu
This commit is contained in:
parent
2fbbddc878
commit
55310971c8
3 changed files with 198 additions and 173 deletions
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Test Worker
|
||||
*/
|
||||
|
||||
module.exports = function(input, done) {
|
||||
|
||||
|
||||
};
|
|
@ -34,10 +34,12 @@ const VERSION = "0.0.1";
|
|||
* @const
|
||||
*/
|
||||
|
||||
const _webSocketServer = require("ws").Server;
|
||||
const _socket = require("ws").Server;
|
||||
const _extend = require("./cmu-utils").extend;
|
||||
const _spawn = require('threads').spawn;
|
||||
const fs = require("fs");
|
||||
|
||||
|
||||
/**
|
||||
* Minimal Command
|
||||
* @constants
|
||||
|
@ -45,7 +47,7 @@ const fs = require("fs");
|
|||
|
||||
const REQUEST_VERSION = "version";
|
||||
const REQUEST_PING = "ping";
|
||||
const REQUEST_APPDRIVE = "appdrive";
|
||||
const REQUEST_SETUP = "setup";
|
||||
|
||||
const RESULT_OK = 200;
|
||||
const RESULT_PONG = 201;
|
||||
|
@ -121,10 +123,10 @@ cmu.prototype = {
|
|||
__construct: function()
|
||||
{
|
||||
// initial app drive
|
||||
this.findAppDrive();
|
||||
this.updateAppDrive();
|
||||
|
||||
// create webserver
|
||||
this.__socket = new _webSocketServer({
|
||||
this.__socket = new _socket({
|
||||
port: this.network.port
|
||||
});
|
||||
|
||||
|
@ -151,69 +153,24 @@ cmu.prototype = {
|
|||
// assing
|
||||
this.client.on('message', function(message) {
|
||||
|
||||
this._log('client:message', message);
|
||||
|
||||
this.handleClientData(client, message);
|
||||
|
||||
}.bind(this));
|
||||
|
||||
this.client.on('close', function() {
|
||||
|
||||
// do nothing
|
||||
});
|
||||
this._log('client:closed');
|
||||
}.bind(this));
|
||||
|
||||
this.client.on('error', function(e) {
|
||||
|
||||
// do nothing
|
||||
});
|
||||
|
||||
// let's try this
|
||||
this.requestLoadJavascript(['test.js']);
|
||||
this._log('client:error', e.message);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* [requestLoadJavascript description]
|
||||
* @param {[type]} files [description]
|
||||
* @param {[type]} path [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
requestLoadJavascript: function(files, path) {
|
||||
|
||||
return this.sendCommand(COMMAND_LOAD_JS, {
|
||||
filenames: files,
|
||||
path: path
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* [requestLoadCSS description]
|
||||
* @param {[type]} files [description]
|
||||
* @param {[type]} path [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
requestLoadCSS: function(files, path) {
|
||||
|
||||
return this.sendCommand(COMMAND_LOAD_CSS, {
|
||||
filenames: files,
|
||||
path: path
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends a command to the client
|
||||
* @param {[type]} command [description]
|
||||
* @param {[type]} payload [description]
|
||||
* @param {[type]} client [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
sendCommand: function(command, attributes, client) {
|
||||
|
||||
this.sendFromPayload(client || this.client, {
|
||||
command: command,
|
||||
attributes: attributes,
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles a client message
|
||||
* @param object client The client instance
|
||||
|
@ -223,7 +180,7 @@ cmu.prototype = {
|
|||
handleClientData: function(client, message, flags) {
|
||||
|
||||
try {
|
||||
var payload = JSON.parse(message);
|
||||
let payload = JSON.parse(message);
|
||||
|
||||
// process minimal command interfae
|
||||
if(payload.request) {
|
||||
|
@ -253,14 +210,20 @@ cmu.prototype = {
|
|||
break;
|
||||
|
||||
/**
|
||||
* Finds the AppDrive
|
||||
* @type REQUEST_APPDRIVE
|
||||
* Setup
|
||||
* @type REQUEST_SETUP
|
||||
*/
|
||||
case REQUEST_APPDRIVE:
|
||||
case REQUEST_SETUP:
|
||||
|
||||
this.sendFromPayload(client, payload, {
|
||||
appdrive: this.appdrive
|
||||
});
|
||||
if(this.appdrive && this.appdrive.enabled) {
|
||||
|
||||
// load javascripts
|
||||
this.requestLoadJavascript(this.resources.js);
|
||||
|
||||
// load css
|
||||
this.requestLoadCSS(this.resources.css);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
@ -289,7 +252,7 @@ cmu.prototype = {
|
|||
*/
|
||||
sendFromPayload: function(client, payload, data, resultCode) {
|
||||
|
||||
var final = JSON.stringify(_extend({}, payload, data, {
|
||||
let final = JSON.stringify(_extend({}, payload, data, {
|
||||
result: resultCode || RESULT_OK
|
||||
}));
|
||||
|
||||
|
@ -297,6 +260,70 @@ cmu.prototype = {
|
|||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sends a command to the client
|
||||
* @param {[type]} command [description]
|
||||
* @param {[type]} payload [description]
|
||||
* @param {[type]} client [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
sendCommand: function(command, attributes, client) {
|
||||
|
||||
this.sendFromPayload(client || this.client, {
|
||||
command: command,
|
||||
attributes: attributes,
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* [requestLoadJavascript description]
|
||||
* @param {[type]} files [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
requestLoadJavascript: function(files) {
|
||||
|
||||
return this.invokeLoadCommand(COMMAND_LOAD_JS, files);
|
||||
},
|
||||
|
||||
/**
|
||||
* [requestLoadCSS description]
|
||||
* @param {[type]} files [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
requestLoadCSS: function(files) {
|
||||
|
||||
return this.invokeLoadCommand(COMMAND_LOAD_CSS, files);
|
||||
},
|
||||
|
||||
/**
|
||||
* [invokeLoadCommand description]
|
||||
* @param {[type]} command [description]
|
||||
* @param {[type]} files [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
invokeLoadCommand: function(command, files) {
|
||||
|
||||
let source = files instanceof Array ? files : ([].push(files)),
|
||||
data = [];
|
||||
|
||||
source.forEach(function(filename) {
|
||||
|
||||
if(this._isFile(filename)) {
|
||||
|
||||
data.push({
|
||||
contents: (fs.readFileSync(filename)).toString(),
|
||||
location: filename
|
||||
});
|
||||
}
|
||||
|
||||
}.bind(this));
|
||||
|
||||
this.sendCommand(command, {
|
||||
data
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the version
|
||||
* @getter
|
||||
|
@ -312,21 +339,27 @@ cmu.prototype = {
|
|||
* @param function callback A callback
|
||||
* @return void
|
||||
*/
|
||||
findAppDrive: function(callback) {
|
||||
updateAppDrive: function(callback) {
|
||||
|
||||
this.appdrive = {
|
||||
locations: {},
|
||||
applications: {},
|
||||
enabled: false,
|
||||
};
|
||||
|
||||
this.workers = {};
|
||||
|
||||
this.resources = {
|
||||
js: [],
|
||||
css: [],
|
||||
};
|
||||
|
||||
var result = [],
|
||||
let result = [],
|
||||
mountPoints = ['sd_nav', 'sda', 'sdb', 'sdc', 'sdd', 'sde', 'sdf'];
|
||||
|
||||
mountPoints.forEach(function(mountPoint) {
|
||||
|
||||
var appDrivePath = [MOUNTROOT_PATH, mountPoint, APPDRIVE_PATH].join(""),
|
||||
let appDrivePath = [MOUNTROOT_PATH, mountPoint, APPDRIVE_PATH].join(""),
|
||||
|
||||
appDriveFilename = [appDrivePath, APPDRIVE_JSON].join(""),
|
||||
|
||||
|
@ -359,9 +392,11 @@ cmu.prototype = {
|
|||
* Load Framework
|
||||
*/
|
||||
|
||||
this.appdrive.js.push([systemPath, SYSTEM_FRAMEWORK_PATH, SYSTEM_FRAMEWORK_JS].join(""));
|
||||
this.resources.js.push([systemPath, SYSTEM_FRAMEWORK_PATH, SYSTEM_FRAMEWORK_JS].join(""));
|
||||
|
||||
this.appdrive.css.push([systemPath, SYSTEM_FRAMEWORK_PATH, SYSTEM_FRAMEWORK_CSS].join(""))
|
||||
this.resources.css.push([systemPath, SYSTEM_FRAMEWORK_PATH, SYSTEM_FRAMEWORK_CSS].join(""))
|
||||
|
||||
this.appdrive.enabled = true;
|
||||
|
||||
/**
|
||||
* Prepare system mount
|
||||
|
@ -379,7 +414,7 @@ cmu.prototype = {
|
|||
* Find Applications
|
||||
*/
|
||||
|
||||
var appFiles = fs.readdirSync(applicationsPath);
|
||||
let appFiles = fs.readdirSync(applicationsPath);
|
||||
|
||||
if(appFiles.length) appFiles.forEach(function(appId) {
|
||||
|
||||
|
@ -390,11 +425,11 @@ cmu.prototype = {
|
|||
|
||||
if(!this.appdrive.applications[appId]) {
|
||||
|
||||
var applicationPath = [applicationsPath, appId, "/"].join("");
|
||||
let applicationPath = [applicationsPath, appId, "/"].join("");
|
||||
|
||||
if(this._isDir(applicationPath)) {
|
||||
|
||||
var profile = {
|
||||
let profile = {
|
||||
id: appId,
|
||||
path: applicationPath,
|
||||
files: {},
|
||||
|
@ -404,7 +439,7 @@ cmu.prototype = {
|
|||
|
||||
parts.forEach(function(filename) {
|
||||
|
||||
var fullFilename = [applicationPath, filename].join("");
|
||||
let fullFilename = [applicationPath, filename].join("");
|
||||
|
||||
if(this._isFile(fullFilename)) {
|
||||
|
||||
|
@ -423,6 +458,8 @@ cmu.prototype = {
|
|||
|
||||
if(found >= 1) {
|
||||
this.appdrive.applications[appId] = profile;
|
||||
|
||||
this.registerWorker(appId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -435,6 +472,30 @@ cmu.prototype = {
|
|||
if(callback) callback(this.appdrive);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Registers a worker to the appid
|
||||
* @param {[type]} appId [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
registerWorker: function(appId) {
|
||||
|
||||
// ensure applications is registered
|
||||
if(!this.appdrive.applications[appId]) return false;
|
||||
|
||||
// ensure worker is eligible
|
||||
if(!this._isFile(this.appdrive.applications[appId].files[APPLICATION_WORKER])) return false;
|
||||
|
||||
// create worker
|
||||
this.workers[appId] = {
|
||||
|
||||
appId: appId,
|
||||
|
||||
thread: _spawn(this.appdrive.applications[appId].files[APPLICATION_WORKER])
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if the file exists
|
||||
* @param string path A string that represents a file path
|
||||
|
@ -473,6 +534,27 @@ cmu.prototype = {
|
|||
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* [__log description]
|
||||
* @param {[type]} name [description]
|
||||
* @param {[type]} description [description]
|
||||
* @param {[type]} attributes [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
_log: function(name, description, attributes) {
|
||||
|
||||
console.log("[" + name + "]", description, attributes ? function() {
|
||||
|
||||
let result = [];
|
||||
|
||||
Object.keys(attributes).forEach(function(element, key, _array) {
|
||||
result.push("[" + element + "=" + _array[key] + "]");
|
||||
});
|
||||
|
||||
return result.join(" ");
|
||||
}.call() : "");
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -46,7 +46,7 @@ window.CMU = {
|
|||
requests: {
|
||||
|
||||
REQUEST_PING: 'ping',
|
||||
REQUEST_APPDRIVE: 'appdrive',
|
||||
REQUEST_SETUP: 'setup',
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -80,7 +80,7 @@ window.CMU = {
|
|||
|
||||
this.initialized = true;
|
||||
|
||||
this.requests = {};
|
||||
this.requestBuffer = {};
|
||||
|
||||
this.obtainConnection();
|
||||
}
|
||||
|
@ -125,6 +125,8 @@ window.CMU = {
|
|||
|
||||
this.__log("connection open");
|
||||
|
||||
this.requestSetup();
|
||||
|
||||
}.bind(this);
|
||||
|
||||
/**
|
||||
|
@ -175,6 +177,15 @@ window.CMU = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* [requestSetup description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
requestSetup: function() {
|
||||
|
||||
this.request(this.requests.REQUEST_SETUP);
|
||||
},
|
||||
|
||||
/**
|
||||
* [request description]
|
||||
* @return {[type]} [description]
|
||||
|
@ -186,12 +197,12 @@ window.CMU = {
|
|||
|
||||
// prepare id
|
||||
var id = false;
|
||||
while(!id || this.requests[id]) {
|
||||
while(!id || this.requestBuffer[id]) {
|
||||
id = (new Date()).getTime();
|
||||
}
|
||||
|
||||
// register request
|
||||
this.requests[id] = callback;
|
||||
this.requestBuffer[id] = callback;
|
||||
|
||||
// sanity check
|
||||
payload = payload || {};
|
||||
|
@ -201,6 +212,8 @@ window.CMU = {
|
|||
|
||||
payload.request = request;
|
||||
|
||||
console.log(payload);
|
||||
|
||||
// execute
|
||||
return this.client.send(JSON.stringify(payload));
|
||||
},
|
||||
|
@ -235,16 +248,16 @@ window.CMU = {
|
|||
default:
|
||||
|
||||
// check against active requests
|
||||
if(payload.requestId && this.requests[payload.requestId]) {
|
||||
if(payload.requestId && this.requestBuffer[payload.requestId]) {
|
||||
|
||||
var callback = this.requests[payload.requestId];
|
||||
var callback = this.requestBuffer[payload.requestId];
|
||||
|
||||
if(typeof(callback) == "function") {
|
||||
|
||||
callback(payload.result == this.results.RESULT_ERROR, payload);
|
||||
}
|
||||
|
||||
delete this.requests[payload.requestId];
|
||||
delete this.requestBuffer[payload.requestId];
|
||||
|
||||
return; // all done
|
||||
}
|
||||
|
@ -270,117 +283,39 @@ window.CMU = {
|
|||
/** @type {LOADJS} [description] */
|
||||
case this.commands.LOAD_JS:
|
||||
|
||||
this.loadJavascript(attributes.filenames, attributes.path);
|
||||
|
||||
this.__loadInvoker(attributes, 'script', 'text/javascript');
|
||||
break;
|
||||
|
||||
/** @type {LOADCSS} */
|
||||
case this.commands.LOAD_CSS:
|
||||
|
||||
this.__loadInvoker(attributes, 'style', 'text/css');
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* (loadJavascript)
|
||||
*/
|
||||
|
||||
loadJavascript: function(scripts, path, callback, options) {
|
||||
|
||||
this.__loadInvoker(scripts, path, function(filename, next) {
|
||||
var script = document.createElement('script');
|
||||
script.type = 'text/javascript';
|
||||
script.src = filename;
|
||||
script.onload = next;
|
||||
document.body.appendChild(script);
|
||||
}, callback, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* (loadCSS)
|
||||
*/
|
||||
|
||||
loadCSS: function(css, path, callback, options) {
|
||||
|
||||
this.__loadInvoker(css, path, function(filename, next) {
|
||||
var css = document.createElement('link');
|
||||
css.rel = "stylesheet";
|
||||
css.type = "text/css";
|
||||
css.href = filename
|
||||
css.onload = async ? callback : next;
|
||||
document.body.appendChild(css);
|
||||
}, callback, options);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* (__loadInvoker)
|
||||
*/
|
||||
|
||||
__loadInvoker: function(input, path, build, callback, options) {
|
||||
__loadInvoker: function(attributes, tag, type) {
|
||||
|
||||
// sanity checks
|
||||
if(typeof(build) != "function") return false;
|
||||
if(!attributes.data || !attributes.data instanceof Array) return false;
|
||||
|
||||
// initialize
|
||||
var ids = false, result = false, options = options ? options : {timeout: 1000}, timeout = false;
|
||||
attributes.data.forEach(function(item) {
|
||||
|
||||
// items need to be an array
|
||||
var items = input instanceof Array ? input : function() {
|
||||
if(item.location && item.contents) {
|
||||
|
||||
var newArray = [];
|
||||
var element = document.createElement(tag);
|
||||
element.setAttribute("data-script-url", item.location);
|
||||
element.appendChild(document.createTextNode(item.contents));
|
||||
|
||||
newArray.push(input);
|
||||
|
||||
return newArray;
|
||||
|
||||
}.call();
|
||||
|
||||
// loaded handler
|
||||
var loaded = 0, next = function(failure) {
|
||||
loaded++;
|
||||
if(loaded >= items.length) {
|
||||
if(typeof(callback) == "function") {
|
||||
callback(result);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// process items
|
||||
items.forEach(function(filename, index) {
|
||||
|
||||
try {
|
||||
|
||||
filename = (path ? path : "") + filename;
|
||||
|
||||
if(options.timeout) {
|
||||
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(function() {
|
||||
|
||||
this.__error("__loadInvoker:timeout", {filename: filename});
|
||||
|
||||
// just do the next one
|
||||
next(true);
|
||||
|
||||
}.bind(this), options.timeout);
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
build(filename, function(resource) {
|
||||
|
||||
next();
|
||||
|
||||
}.bind(this), ids ? ids[index] : false);
|
||||
|
||||
} catch(error) {
|
||||
next(true);
|
||||
}
|
||||
|
||||
} catch(error) {
|
||||
this.__error("__loadInvoker:loaderror", {error: error, filename: filename});
|
||||
if(type) element.setAttribute("type", type);
|
||||
document.head.appendChild(element);
|
||||
}
|
||||
|
||||
}.bind(this));
|
||||
|
||||
return true;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue