diff --git a/.gitignore b/.gitignore
index 59d842b..0e80248 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+node_modules
+bower_components
+
# Logs
logs
*.log
diff --git a/desirae b/desirae
index 311e731..f023315 160000
--- a/desirae
+++ b/desirae
@@ -1 +1 @@
-Subproject commit 311e731aa1db6facfb092c7b9449904d6adb8c3e
+Subproject commit f023315cfc91001e608b00892de5379e9b2c0eee
diff --git a/index.html b/index.html
index bf956ca..5803871 100644
--- a/index.html
+++ b/index.html
@@ -84,22 +84,22 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
+
diff --git a/package.json b/package.json
index 6def25c..220a12f 100644
--- a/package.json
+++ b/package.json
@@ -31,5 +31,16 @@
"bugs": {
"url": "https://github.com/DearDesi/deardesi/issues"
},
- "homepage": "https://github.com/DearDesi/deardesi"
+ "homepage": "https://github.com/DearDesi/deardesi",
+ "dependencies": {
+ "bluebird": "^2.6.4",
+ "body-parser": "^1.10.1",
+ "compression": "^1.3.0",
+ "connect": "^3.3.4",
+ "connect-query": "^0.2.0",
+ "connect-send-json": "^1.0.0",
+ "fs.extra": "^1.3.0",
+ "require-yaml": "0.0.1",
+ "serve-static": "^1.8.0"
+ }
}
diff --git a/server.js b/server.js
new file mode 100644
index 0000000..46ff0ad
--- /dev/null
+++ b/server.js
@@ -0,0 +1,173 @@
+'use strict';
+
+require('require-yaml');
+
+var connect = require('connect')
+ //, PromiseA = require('bluebird').Promise
+ , query = require('connect-query')
+ , bodyParser = require('body-parser')
+ , serveStatic = require('serve-static')
+ , send = require('connect-send-json')
+
+ , app = connect()
+ , fsapi = require('./desirae/lib/fsapi')
+ , walk = require('./desirae/lib/fsapi').walk
+ , getfs = require('./desirae/lib/fsapi').getfs
+ , putfs = require('./desirae/lib/fsapi').putfs
+
+ , blogdir = process.argv[2]
+ , port = process.argv[3] || '65080'
+
+ , path = require('path')
+ //, config = require(path.join('./', blogdir, 'config.yml'))
+ ;
+
+if (!blogdir) {
+ console.error("Usage: deardesi ~/path/to/blog");
+ process.exit(1);
+ return;
+}
+
+app
+ .use(send.json())
+ .use(query())
+ .use(bodyParser.json({ limit: 10 * 1024 * 1024 })) // 10mb
+ .use(require('compression')())
+ .use('/api/fs/walk', function (req, res, next) {
+ if (!(/^GET$/i.test(req.method) || /^GET$/i.test(req.query._method))) {
+ next();
+ return;
+ }
+
+ var opts = {}
+ , dirnames = req.query.dir && [req.query.dir] || (req.query.dirs && req.query.dirs.split(/,/g)) || req.body.dirs
+ ;
+
+ if (!dirnames || !dirnames.length) {
+ res.json({ error: "please specify GET w/ req.query.dir or POST w/ _method=GET&dirs=path/to/thing,..." });
+ return;
+ }
+
+ if (!dirnames.every(function (dirname) {
+ return 'string' === typeof dirname;
+ })) {
+ res.json({ error: "malformed request: " + JSON.stringify(dirnames) });
+ return;
+ }
+
+ /*
+ if (req.query.excludes) {
+ opts.excludes = req.query.excludes.split(',');
+ }
+ */
+
+ if (req.query.extensions) {
+ opts.extensions = req.query.extensions.split(/,/g);
+ }
+
+ if ('true' === req.query.dotfiles) {
+ opts.dotfiles = true;
+ }
+ if ('false' === req.query.sha1sum) {
+ opts.sha1sum = false;
+ }
+ if ('true' === req.query.contents) {
+ opts.contents = true;
+ }
+
+ // TODO opts.contents?
+ walk.walkDirs(blogdir, dirnames, opts).then(function (stats) {
+ if (!req.body.dirs && !req.query.dirs) {
+ res.json(stats[dirnames[0]]);
+ } else {
+ res.json(stats);
+ }
+ });
+ })
+ .use('/api/fs/files', function (req, res, next) {
+ if (!(/^GET$/i.test(req.method) || /^GET$/i.test(req.query._method))) {
+ next();
+ return;
+ }
+
+ var filepaths = req.query.path && [req.query.path] || (req.query.paths && req.query.paths.split(/,/g)) || req.body.paths
+ ;
+
+ if (!filepaths || !filepaths.length) {
+ res.json({ error: "please specify GET w/ req.query.path or POST _method=GET&paths=path/to/thing,..." });
+ return;
+ }
+
+ return getfs(blogdir, filepaths).then(function (files) {
+ if (!req.body.paths && !req.query.paths) {
+ res.json(files[0]);
+ } else {
+ res.send(files);
+ }
+ });
+ })
+ .use('/api/fs/files', function (req, res, next) {
+ if (!(/^POST|PUT$/i.test(req.method) || /^POST|PUT$/i.test(req.query._method))) {
+ next();
+ return;
+ }
+
+ var opts = {}
+ , files = req.body.files
+ ;
+
+ if (!files || !files.length) {
+ res.json({ error: "please specify POST w/ req.body.files" });
+ return;
+ }
+
+ return putfs(blogdir, files, opts).then(function (results) {
+ res.json(results);
+ });
+ })
+ .use('/api/fs/copy', function (req, res, next) {
+ if (!(/^POST|PUT$/i.test(req.method) || /^POST|PUT$/i.test(req.query._method))) {
+ next();
+ return;
+ }
+
+ var opts = {}
+ , files = req.body.files
+ ;
+
+ if ('object' !== typeof files || !Object.keys(files).length) {
+ res.json({ error: "please specify POST w/ req.body.files" });
+ return;
+ }
+
+ return fsapi.copyfs(blogdir, files, opts).then(function (results) {
+ res.json(results);
+ });
+ })
+
+ .use('/api/fs', function (req, res) {
+ var pathname = path.resolve(blogdir)
+ ;
+
+ res.json({
+ path: pathname
+ , name: path.basename(pathname)
+ , relativePath: path.dirname(pathname)
+ //, cwd: path.resolve()
+ //, patharg: blogdir
+ });
+ return;
+ })
+ .use('/api/fs/static', serveStatic(blogdir))
+
+ .use(serveStatic('./'))
+ .use('/compiled_dev', serveStatic(path.join(blogdir, '/compiled_dev')))
+ // TODO
+ //.use(serveStatic(tmpdir))
+ ;
+
+module.exports = app;
+
+require('http').createServer().on('request', app).listen(port, function () {
+ console.log('listening from ' + blogdir + ' http://local.dear.desi:' + port);
+});