diff --git a/core/modules/server/routes/post-commands.js b/core/modules/server/routes/post-commands.js new file mode 100644 index 000000000..1bd2137e5 --- /dev/null +++ b/core/modules/server/routes/post-commands.js @@ -0,0 +1,57 @@ +/*\ +title: $:/core/modules/server/routes/post-commands.js +type: application/javascript +module-type: route + +POST /commands/ + +\*/ +(function() { + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.method = "POST"; + +exports.path = /^\/commands\/$/; + +exports.handler = function(request,response,state) { + // Check we're enabled + +console.log("wikiInfo",$tw.boot.wikiInfo) + if(!($tw.boot.wikiInfo.config || {})["allow-remote-commands"]) { + response.writeHead(404); + response.end(); + return; + } + // Get the job descriptor + var jobDescriptor = JSON.parse(state.data); + console.log("JOB START:",jobDescriptor) + // Respond OK + response.writeHead(204, "OK",{ + "Content-Type": "application/json" + }); + // Maintain status + var setStatus = function(status,message) { + if(jobDescriptor.statusTitle) { + state.wiki.addTiddler(new $tw.Tiddler({title: jobDescriptor.statusTitle,text: status,message: message})); + } + } + setStatus("started"); + // Initiate the commands + var commander = new $tw.Commander( + jobDescriptor.commands || [], + function(err) { + setStatus(err ? "error" : "ok",err ? err : undefined); + console.log("JOB END:",err) + }, + state.wiki, + {output: process.stdout, error: process.stderr} + ); + commander.execute(); + // Return results + response.end(JSON.stringify({}),"utf8"); // Nothing useful for us to return +}; + +}()); diff --git a/core/modules/syncer.js b/core/modules/syncer.js index e6d86ea61..3a0743b6e 100644 --- a/core/modules/syncer.js +++ b/core/modules/syncer.js @@ -84,6 +84,11 @@ function Syncer(options) { $tw.rootWidget.addEventListener("tm-server-refresh",function() { self.handleRefreshEvent(); }); + $tw.rootWidget.addEventListener("tm-execute-job",function(event) { + if(self.syncadaptor && self.syncadaptor.executeJob) { + self.syncadaptor.executeJob(event); + } + }); } // Listen out for lazyLoad events if(!this.disableUI) { diff --git a/plugins/tiddlywiki/tiddlyweb/tiddlywebadaptor.js b/plugins/tiddlywiki/tiddlyweb/tiddlywebadaptor.js index 492909324..f5c064027 100644 --- a/plugins/tiddlywiki/tiddlyweb/tiddlywebadaptor.js +++ b/plugins/tiddlywiki/tiddlyweb/tiddlywebadaptor.js @@ -140,6 +140,46 @@ TiddlyWebAdaptor.prototype.getCsrfToken = function() { return csrf; }; +/* +*/ +TiddlyWebAdaptor.prototype.executeJob = function(event,callback) { + var paramObject = event.paramObject || {}; + // Collect the commands + var commands; + if(paramObject.commands) { + commands = $tw.utils.parseStringArray(paramObject.commands); + } else { + // Get the values of the numeric parameters and sort them by their numeric name + commands = Object.keys(paramObject).filter(function(name) { + // We just include parameters that are identical to their numeric representation + return (parseInt(name,10) + "") === name; + }).map(function(name) { + return parseInt(name,10); + }).sort().map(function(index) { + return paramObject[index + ""]; + }); + } + // Compose the request + var options = { + url: this.host + "commands/", + type: "POST", + data: JSON.stringify({ + commands: commands, + statusTitle: paramObject.statusTitle, + outputTitle: paramObject.outputTitle, + errorTitle: paramObject.errorTitle + }), + callback: function(err,data) { + if(callback) { + callback(err,data); + } + } + }; + // Send the request + this.logger.log("Executing job:",options); + $tw.utils.httpRequest(options); +}; + /* Get an array of skinny tiddler fields from the server */