parent
597bdda80c
commit
4f38c81e2d
@ -0,0 +1,2 @@ |
||||
node_modules |
||||
npm-debug.log |
@ -0,0 +1,16 @@ |
||||
#!/usr/bin/env node
|
||||
var Router = require('./router') |
||||
var program = require('commander') |
||||
program |
||||
.usage('remix -S <shared folder>') |
||||
.description('Provide a two ways connection between the local computer and Remix IDE') |
||||
.option('-S, --shared-folder <path>', 'Folder to share with Remix IDE') |
||||
.parse(process.argv) |
||||
|
||||
if (!program.sharedFolder) { |
||||
program.outputHelp() |
||||
process.exit(1) |
||||
} |
||||
|
||||
var router = new Router() |
||||
router.start(program.sharedFolder) |
@ -0,0 +1,28 @@ |
||||
var servicesList = require('./servicesList') |
||||
var Websocket = require('./websocket') |
||||
|
||||
class Router { |
||||
start (sharedFolder) { |
||||
this.websocket = new Websocket() |
||||
this.websocket.start((message) => { |
||||
this.call(message.id, message.service, message.fn, message.args) |
||||
}) |
||||
servicesList['sharedfolder'].setupNotifications(this.websocket, sharedFolder) |
||||
servicesList['sharedfolder'].sharedFolder(sharedFolder) |
||||
} |
||||
|
||||
call (callid, name, fn, args) { |
||||
servicesList[name][fn](args, (error, data) => { |
||||
var response = { |
||||
id: callid, |
||||
type: 'reply', |
||||
scope: name, |
||||
result: data, |
||||
error: error |
||||
} |
||||
this.websocket.send(JSON.stringify(response)) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
module.exports = Router |
@ -0,0 +1,87 @@ |
||||
var utils = require('../utils') |
||||
var isbinaryfile = require('isbinaryfile') |
||||
var fs = require('fs-extra') |
||||
var watch = require('watch') |
||||
|
||||
module.exports = { |
||||
monitors: [], |
||||
trackDownStreamUpdate: {}, |
||||
|
||||
sharedFolder: function (sharedFolder) { |
||||
this.sharedFolder = sharedFolder |
||||
}, |
||||
|
||||
list: function (args, cb) { |
||||
cb(null, utils.walkSync(this.sharedFolder, {}, this.sharedFolder)) |
||||
}, |
||||
|
||||
get: function (args, cb) { |
||||
var path = utils.absolutePath(args.path, this.sharedFolder) |
||||
isbinaryfile(path, (error, isBinary) => { |
||||
if (error) console.log(error) |
||||
if (isBinary) { |
||||
cb(null, '<binary content not displayed>') |
||||
} else { |
||||
fs.readFile(path, 'utf8', (error, data) => { |
||||
if (error) console.log(error) |
||||
cb(error, data) |
||||
}) |
||||
} |
||||
}) |
||||
}, |
||||
|
||||
set: function (args, cb) { |
||||
var path = utils.absolutePath(args.path, this.sharedFolder) |
||||
this.trackDownStreamUpdate[path] = path |
||||
fs.writeFile(path, args.content, 'utf8', (error, data) => { |
||||
if (error) console.log(error) |
||||
cb(error, data) |
||||
}) |
||||
}, |
||||
|
||||
rename: function (args, cb) { |
||||
var oldpath = utils.absolutePath(args.oldPath, this.sharedFolder) |
||||
var newpath = utils.absolutePath(args.newPath, this.sharedFolder) |
||||
fs.move(oldpath, newpath, (error, data) => { |
||||
if (error) console.log(error) |
||||
cb(error, data) |
||||
}) |
||||
}, |
||||
|
||||
remove: function (args, cb) { |
||||
var path = utils.absolutePath(args.path, this.sharedFolder) |
||||
fs.remove(path, (error, data) => { |
||||
if (error) console.log(error) |
||||
cb(error, data) |
||||
}) |
||||
}, |
||||
|
||||
setupNotifications: function (websocket, path) { |
||||
watch.createMonitor(path, (monitor) => { |
||||
this.monitors.push(monitor) |
||||
monitor.on('created', (f, stat) => { |
||||
isbinaryfile(f, (error, isBinary) => { |
||||
if (error) console.log(error) |
||||
if (stat.isDirectory()) { |
||||
this.setupNotifications(websocket, f) |
||||
} |
||||
if (websocket.connection) websocket.send(message('created', { path: utils.relativePath(f, this.sharedFolder), isReadOnly: isBinary, isFolder: stat.isDirectory() })) |
||||
}) |
||||
}) |
||||
monitor.on('changed', (f, curr, prev) => { |
||||
if (this.trackDownStreamUpdate[f]) { |
||||
delete this.trackDownStreamUpdate[f] |
||||
return |
||||
} |
||||
if (websocket.connection) websocket.send(message('changed', utils.relativePath(f, this.sharedFolder))) |
||||
}) |
||||
monitor.on('removed', (f, stat) => { |
||||
if (websocket.connection) websocket.send(message('removed', { path: utils.relativePath(f, this.sharedFolder), isFolder: stat.isDirectory() })) |
||||
}) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
function message (name, value) { |
||||
return JSON.stringify({type: 'notification', scope: 'sharedfolder', name: name, value: value}) |
||||
} |
@ -0,0 +1,3 @@ |
||||
module.exports = { |
||||
sharedfolder: require('./services/sharedFolder') |
||||
} |
@ -0,0 +1,59 @@ |
||||
var fs = require('fs-extra') |
||||
var path = require('path') |
||||
var isbinaryfile = require('isbinaryfile') |
||||
var pathModule = require('path') |
||||
|
||||
module.exports = { |
||||
absolutePath: absolutePath, |
||||
relativePath: relativePath, |
||||
walkSync: walkSync |
||||
} |
||||
|
||||
/** |
||||
* returns the absolute path of the given @arg path |
||||
* |
||||
* @param {String} path - relative path (Unix style which is the one used by Remix IDE) |
||||
* @param {String} sharedFolder - absolute shared path. platform dependent representation. |
||||
* @return {String} platform dependent absolute path (/home/user1/.../... for unix, c:\user\...\... for windows) |
||||
*/ |
||||
function absolutePath (path, sharedFolder) { |
||||
path = normalizePath(path) |
||||
if (path.indexOf(sharedFolder) !== 0) { |
||||
path = pathModule.resolve(sharedFolder, path) |
||||
} |
||||
return path |
||||
} |
||||
|
||||
/** |
||||
* return the relative path of the given @arg path |
||||
* |
||||
* @param {String} path - absolute platform dependent path |
||||
* @param {String} sharedFolder - absolute shared path. platform dependent representation |
||||
* @return {String} relative path (Unix style which is the one used by Remix IDE) |
||||
*/ |
||||
function relativePath (path, sharedFolder) { |
||||
var relative = pathModule.relative(sharedFolder, path) |
||||
return normalizePath(relative) |
||||
} |
||||
|
||||
function normalizePath (path) { |
||||
if (process.platform === 'win32') { |
||||
return path.replace(/\\/g, '/') |
||||
} |
||||
return path |
||||
} |
||||
|
||||
function walkSync (dir, filelist, sharedFolder) { |
||||
var files = fs.readdirSync(dir) |
||||
filelist = filelist || {} |
||||
files.forEach(function (file) { |
||||
var subElement = path.join(dir, file) |
||||
if (fs.statSync(subElement).isDirectory()) { |
||||
filelist = walkSync(subElement, filelist, sharedFolder) |
||||
} else { |
||||
var relative = relativePath(subElement, sharedFolder) |
||||
filelist[relative] = isbinaryfile.sync(subElement) |
||||
} |
||||
}) |
||||
return filelist |
||||
} |
@ -0,0 +1,62 @@ |
||||
#!/usr/bin/env node
|
||||
var WebSocketServer = require('websocket').server |
||||
var http = require('http') |
||||
|
||||
class WebSocket { |
||||
constructor () { |
||||
this.connection = null |
||||
} |
||||
|
||||
start (callback) { |
||||
var server = http.createServer(function (request, response) { |
||||
console.log((new Date()) + ' Received request for ' + request.url) |
||||
response.writeHead(404) |
||||
response.end() |
||||
}) |
||||
server.listen(65520, function () { |
||||
console.log((new Date()) + ' Remixd is listening on port 65520') |
||||
}) |
||||
|
||||
this.wsServer = new WebSocketServer({ |
||||
httpServer: server, |
||||
autoAcceptConnections: false |
||||
}) |
||||
|
||||
this.wsServer.on('request', (request) => { |
||||
if (!originIsAllowed(request.origin)) { |
||||
request.reject() |
||||
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.') |
||||
return |
||||
} |
||||
if (this.connection) { |
||||
console.log('closing previous connection') |
||||
this.wsServer.closeAllConnections() |
||||
this.connection = null |
||||
return |
||||
} |
||||
|
||||
this.connection = request.accept('echo-protocol', request.origin) |
||||
console.log((new Date()) + ' Connection accepted.') |
||||
this.connection.on('message', (message) => { |
||||
if (message.type === 'utf8') { |
||||
callback(JSON.parse(message.utf8Data)) |
||||
} |
||||
}) |
||||
this.connection.on('close', (reasonCode, description) => { |
||||
console.log((new Date()) + ' Remix ' + this.connection.remoteAddress + ' disconnected.') |
||||
this.connection = null |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
send (data) { |
||||
this.connection.sendUTF(data) |
||||
} |
||||
} |
||||
|
||||
function originIsAllowed (origin) { |
||||
console.log('origin', origin) |
||||
return true |
||||
} |
||||
|
||||
module.exports = WebSocket |
Loading…
Reference in new issue