]> git.immae.eu Git - perso/Immae/Projets/Nodejs/Surfer.git/commitdiff
Support recursive put
authorJohannes Zellner <johannes@nebulon.de>
Sat, 27 Jun 2015 15:07:42 +0000 (17:07 +0200)
committerJohannes Zellner <johannes@nebulon.de>
Sat, 27 Jun 2015 15:07:42 +0000 (17:07 +0200)
app.js
cli/actions.js [new file with mode: 0644]
cli/config.js [new file with mode: 0644]
cli/surfer.js [new file with mode: 0755]
package.json
src/actions.js [deleted file]
src/files.js
surfer.js [deleted file]

diff --git a/app.js b/app.js
index 196473f85b566a8e81e04a7eedcbcefe95caba02..69607648a62a320499062f5708b35a1857a3fbe4 100755 (executable)
--- a/app.js
+++ b/app.js
@@ -4,11 +4,12 @@
 
 var express = require('express'),
     morgan = require('morgan'),
+    path = require('path'),
     compression = require('compression'),
     bodyParser = require('body-parser'),
     lastMile = require('connect-lastmile'),
     multipart = require('./src/multipart'),
-    files = require('./src/files.js');
+    files = require('./src/files.js')(path.resolve(__dirname, 'files'));
 
 var app = express();
 var router = new express.Router();
diff --git a/cli/actions.js b/cli/actions.js
new file mode 100644 (file)
index 0000000..592d809
--- /dev/null
@@ -0,0 +1,96 @@
+'use strict';
+
+exports.login = login;
+exports.put = put;
+exports.get = get;
+exports.del = del;
+
+var superagent = require('superagent'),
+    config = require('./config'),
+    async = require('async'),
+    fs = require('fs'),
+    path = require('path');
+
+require('colors');
+
+var API = '/api/files/';
+
+function checkConfig() {
+    if (!config.server()) {
+        console.log('You have run "login" first');
+        process.exit(1);
+    }
+}
+
+function collectFiles(filesOrFolders) {
+    var tmp = [];
+
+    filesOrFolders.forEach(function (filePath) {
+        var stat = fs.statSync(filePath);
+
+        if (stat.isFile()) {
+            tmp.push(filePath);
+        } else if (stat.isDirectory()) {
+            var files = fs.readdirSync(filePath).map(function (file) { return path.join(filePath, file); });
+            tmp = tmp.concat(collectFiles(files));
+        } else {
+            console.log('Skipping %s', filePath.cyan);
+        }
+    });
+
+    return tmp;
+}
+
+function login(server) {
+    console.log('Using server', server);
+    config.set('server', server);
+}
+
+function put(filePath, otherFilePaths) {
+    checkConfig();
+
+    var files = collectFiles([ filePath ].concat(otherFilePaths));
+
+    async.eachSeries(files, function (file, callback) {
+        var relativeFilePath = path.resolve(file).slice(process.cwd().length + 1);
+
+        console.log('Uploading file %s', relativeFilePath.cyan);
+
+        superagent.put(config.server() + API + relativeFilePath).attach('file', file).end(callback);
+    }, function (error) {
+        if (error) {
+            console.log('Failed to put file.', error);
+            process.exit(1);
+        }
+
+        console.log('Done');
+    });
+}
+
+function get(filePath) {
+    checkConfig();
+
+    var relativeFilePath = path.resolve(filePath).slice(process.cwd().length + 1);
+    superagent.get(config.server() + API + relativeFilePath).end(function (error, result) {
+        if (error) return console.log('Failed', result ? result.body : error);
+
+        if (result.body && result.body.entries) {
+            console.log('Files:');
+            result.body.entries.forEach(function (entry) {
+                console.log('\t %s', entry);
+            });
+        } else {
+            console.log(result.text);
+        }
+    });
+}
+
+function del(filePath) {
+    checkConfig();
+
+    var relativeFilePath = path.resolve(filePath).slice(process.cwd().length + 1);
+    superagent.del(config.server() + API + relativeFilePath).end(function (error, result) {
+        if (error) return console.log('Failed', result ? result.body : error);
+        console.log('Success', result.body);
+    });
+}
diff --git a/cli/config.js b/cli/config.js
new file mode 100644 (file)
index 0000000..a3708b8
--- /dev/null
@@ -0,0 +1,62 @@
+/* jshint node:true */
+
+'use strict';
+
+var fs = require('fs'),
+    path = require('path'),
+    safe = require('safetydance'),
+    _ = require('underscore');
+
+exports = module.exports = {
+    clear: clear,
+    set: set,
+    get: get,
+    unset: unset,
+    has: has,
+
+    // convenience
+    server: function () { return get('server'); }
+};
+
+var HOME = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
+var CONFIG_FILE_PATH = path.join(HOME, '.surfer.json');
+
+var gConfig = (function () {
+    return safe.JSON.parse(safe.fs.readFileSync(CONFIG_FILE_PATH)) || {};
+})();
+
+function save() {
+    fs.writeFileSync(CONFIG_FILE_PATH, JSON.stringify(gConfig, null, 4));
+}
+
+function clear() {
+    safe.fs.unlinkSync(CONFIG_FILE_PATH);
+}
+
+function set(key, value) {
+    if (typeof key === 'object') {
+        _.extend(gConfig, key);
+    } else {
+        safe.set(gConfig, key, value);
+    }
+    save();
+}
+
+function get(key) {
+    return safe.query(gConfig, key);
+}
+
+function unset(key /*, .... */) {
+    for (var i = 0; i < arguments.length; i++) {
+        gConfig = safe.unset(gConfig, arguments[i]);
+    }
+
+    save();
+}
+
+function has(key /*, ... */) {
+    for (var i = 0; i < arguments.length; i++) {
+        if (!(arguments[i] in gConfig)) return false;
+    }
+    return true;
+}
diff --git a/cli/surfer.js b/cli/surfer.js
new file mode 100755 (executable)
index 0000000..d906d62
--- /dev/null
@@ -0,0 +1,39 @@
+#!/usr/bin/env node
+
+'use strict';
+
+var program = require('commander'),
+    actions = require('./actions');
+
+// Allow self signed certs!
+process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
+
+program.version('0.1.0');
+
+program.command('login')
+    .description('Login to server')
+    .action(actions.login);
+
+program.command('put <file> [files...]')
+    .description('Put a file')
+    .action(actions.put);
+
+program.command('get')
+    .description('Get a file or directory')
+    .action(actions.get);
+
+program.command('del')
+    .description('Delete a file')
+    .action(actions.del);
+
+program.parse(process.argv);
+
+if (!process.argv.slice(2).length) {
+    program.outputHelp();
+} else { // https://github.com/tj/commander.js/issues/338
+    var knownCommand = program.commands.some(function (command) { return command._name === process.argv[2]; });
+    if (!knownCommand) {
+        console.error('Unknown command: ' + process.argv[2]);
+        process.exit(1);
+    }
+}
index e5eb25d916d06abbebbb5978fc0d0cf881f4c032..5e97c28dc28606f572f47ef4f08caa1a9eb569ae 100644 (file)
     "file",
     "server"
   ],
+  "bin": {
+    "surfer": "./cli/surfer.js"
+  },
   "author": "Johannes Zellner <johannes@nebulon.de>",
   "license": "MIT",
   "dependencies": {
+    "async": "^1.2.1",
     "body-parser": "^1.13.1",
+    "colors": "^1.1.2",
     "commander": "^2.8.1",
     "compression": "^1.5.0",
     "connect-lastmile": "0.0.10",
     "connect-timeout": "^1.6.2",
+    "debug": "^2.2.0",
     "ejs": "^2.3.1",
     "express": "^4.12.4",
     "mkdirp": "^0.5.1",
     "morgan": "^1.6.0",
     "multiparty": "^4.1.2",
     "rimraf": "^2.4.0",
-    "superagent": "^1.2.0"
+    "safetydance": "0.0.16",
+    "superagent": "^1.2.0",
+    "underscore": "^1.8.3"
   }
 }
diff --git a/src/actions.js b/src/actions.js
deleted file mode 100644 (file)
index 33e47aa..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-'use strict';
-
-exports.put = put;
-exports.get = get;
-exports.del = del;
-
-var superagent = require('superagent'),
-    path = require('path');
-
-var server = 'http://localhost:3000/api/files/';
-
-function put(filePath) {
-    var relativeFilePath = path.resolve(filePath).slice(process.cwd().length + 1);
-    superagent.put(server + relativeFilePath).attach('file', filePath).end(function (error, result) {
-        if (error) return console.log('Failed', result ? result.body : error);
-        console.log('Success', result.body);
-    });
-}
-
-function get(filePath) {
-    var relativeFilePath = path.resolve(filePath).slice(process.cwd().length + 1);
-    superagent.get(server + relativeFilePath).end(function (error, result) {
-        if (error) return console.log('Failed', result ? result.body : error);
-        console.log('Success', result.body);
-    });
-}
-
-function del(filePath) {
-    var relativeFilePath = path.resolve(filePath).slice(process.cwd().length + 1);
-    superagent.del(server + relativeFilePath).end(function (error, result) {
-        if (error) return console.log('Failed', result ? result.body : error);
-        console.log('Success', result.body);
-    });
-}
index 3812d21d063327cbeb726d1f26eeacc1c6794e32..48f91a816574808cea9939c2ee4006cb5354066d 100644 (file)
@@ -4,17 +4,22 @@ var fs = require('fs'),
     path = require('path'),
     ejs = require('ejs'),
     rimraf = require('rimraf'),
+    debug = require('debug')('files'),
     mkdirp = require('mkdirp'),
     HttpError = require('connect-lastmile').HttpError,
     HttpSuccess = require('connect-lastmile').HttpSuccess;
 
-exports = module.exports = {
-    get: get,
-    put: put,
-    del: del
-};
+var gBasePath;
+
+exports = module.exports = function (basePath) {
+    gBasePath = basePath;
 
-var FILE_BASE = path.resolve(__dirname, '../files');
+    return {
+        get: get,
+        put: put,
+        del: del
+    };
+};
 
 // http://stackoverflow.com/questions/11293857/fastest-way-to-copy-file-in-node-js
 function copyFile(source, target, cb) {
@@ -54,9 +59,9 @@ function render(view, options) {
 }
 
 function getAbsolutePath(filePath) {
-    var absoluteFilePath = path.resolve(FILE_BASE, filePath);
+    var absoluteFilePath = path.resolve(gBasePath, filePath);
 
-    if (absoluteFilePath.indexOf(FILE_BASE) !== 0) return null;
+    if (absoluteFilePath.indexOf(gBasePath) !== 0) return null;
     return absoluteFilePath;
 }
 
@@ -68,7 +73,7 @@ function get(req, res, next) {
     fs.stat(absoluteFilePath, function (error, result) {
         if (error) return next(new HttpError(404, error));
 
-        console.log('get', absoluteFilePath);
+        debug('get', absoluteFilePath);
 
         if (result.isFile()) return res.sendfile(absoluteFilePath);
         if (result.isDirectory()) return res.status(200).send({ entries: fs.readdirSync(absoluteFilePath) });
@@ -88,7 +93,7 @@ function put(req, res, next) {
     fs.stat(absoluteFilePath, function (error, result) {
         if (error && error.code !== 'ENOENT') return next(new HttpError(500, error));
 
-        console.log('put', absoluteFilePath, req.files.file);
+        debug('put', absoluteFilePath, req.files.file);
 
         if (result && result.isDirectory()) return next(new HttpError(409, 'cannot put on directories'));
         if (!result || result.isFile()) {
@@ -106,7 +111,7 @@ function del(req, res, next) {
     var filePath = req.params[0];
     var absoluteFilePath = getAbsolutePath(filePath);
     if (!absoluteFilePath) return next(new HttpError(404, 'Not found'));
-    if (absoluteFilePath.slice(FILE_BASE.length) === '') return next(new HttpError(403, 'Forbidden'));
+    if (absoluteFilePath.slice(gBasePath.length) === '') return next(new HttpError(403, 'Forbidden'));
 
     fs.stat(absoluteFilePath, function (error, result) {
         if (error) return next(new HttpError(404, error));
diff --git a/surfer.js b/surfer.js
deleted file mode 100755 (executable)
index 703fc59..0000000
--- a/surfer.js
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env node
-
-'use strict';
-
-var program = require('commander'),
-    actions = require('./src/actions');
-
-// Allow self signed certs!
-process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
-
-program.version('0.1.0');
-
-program.command('put')
-    .description('Put a file')
-    .action(actions.put);
-
-program.command('get')
-    .description('Get a file or directory')
-    .action(actions.get);
-
-program.command('del')
-    .description('Delete a file')
-    .action(actions.del);
-
-program.parse(process.argv);