add some README, fsapi works!
This commit is contained in:
		
							parent
							
								
									3b19c4e877
								
							
						
					
					
						commit
						a44478de87
					
				
							
								
								
									
										115
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								README.md
									
									
									
									
									
								
							| @ -1,4 +1,115 @@ | |||||||
| nuhoh | Desirae | ||||||
| ===== | ===== | ||||||
| 
 | 
 | ||||||
| Blog Platform. A Ruhoh knock-off written in JavaScript | In development. | ||||||
|  | 
 | ||||||
|  | Blog Platform. A Ruhoh knock-off written in JavaScript for the Browser | ||||||
|  | 
 | ||||||
|  | Key Features | ||||||
|  | ------------ | ||||||
|  | 
 | ||||||
|  | Really good use of `try { ... } catch(e) ...` - it won't all blow up at the slightest parse error (*cough* ruhoh *cough* jekyll)... bless me. | ||||||
|  | 
 | ||||||
|  | JavaScript - it's so stable it takes 10 years to get new any features. Won't break every time you upgrade OS X and reinstall brew (*cough* ruby). | ||||||
|  | 
 | ||||||
|  | Browser (optional) - using your front-end templates to build in your front-end? Imagine that! | ||||||
|  | 
 | ||||||
|  | Node (optional) - if you'd prefer to go headless, you can. | ||||||
|  | 
 | ||||||
|  | The server is *very* minimal and could easily be implemented in any language (such as ruby or python). | ||||||
|  | 
 | ||||||
|  | Server | ||||||
|  | ====== | ||||||
|  | 
 | ||||||
|  | Obviously there has to be a server with some sort of storage and retrieval mechanism. | ||||||
|  | 
 | ||||||
|  | I've implemented a very simple node server using the filesystem. | ||||||
|  | 
 | ||||||
|  | /api/fs/walk | ||||||
|  | ------------ | ||||||
|  | 
 | ||||||
|  | `GET http://local.dear.desi:8080/api/fs/walk?dir=posts&dotfiles=true&extensions=md,markdown,jade,htm,html` | ||||||
|  | 
 | ||||||
|  | * `dir` **must** be supplied. returns a flat list of all files, recursively | ||||||
|  | * `dotfiles` default to `false`. includes dotfiles when `true`. | ||||||
|  | * `extensions` defaults to `null`. inclode **only** the supplied extensions when `true`. | ||||||
|  | 
 | ||||||
|  | ```json | ||||||
|  | [ | ||||||
|  |   { "name": "happy-new-year.md" | ||||||
|  |   , "lastModifiedDate": "2015-01-05T18:19:30.000Z" | ||||||
|  |   , "size": 2121 | ||||||
|  |   , "relativePath": "posts/2015" | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | , { "name": "tips-for-the-ages.jade" | ||||||
|  |   , "lastModifiedDate": "2014-06-16T18:19:30.000Z" | ||||||
|  |   , "size": 389 | ||||||
|  |   , "relativePath": "posts" | ||||||
|  |   } | ||||||
|  | , { "name": "my-first-post.html" | ||||||
|  |   , "lastModifiedDate": "2013-08-01T22:47:37.000Z" | ||||||
|  |   , "size": 4118 | ||||||
|  |   , "relativePath": "posts/2013" | ||||||
|  |   } | ||||||
|  | ] | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | To retrieve multiple dir listings at once: | ||||||
|  | 
 | ||||||
|  | * for a few simple dirs without special chars just change `dir` to `dirs` and separate with commas | ||||||
|  | 
 | ||||||
|  | `GET http://local.dear.desi:8080/api/fs/walk?dirs=posts/2015,posts/2013&dotfiles=true&extensions=md,markdown,jade,htm,html` | ||||||
|  | 
 | ||||||
|  | * for many dirs, or dirs with special chars, `POST` an object containing an array of `dirs` with  `&_method=GET` appended to the url. | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | POST http://local.dear.desi:8080/api/fs/walk?dotfiles=true&extensions=md,markdown,jade,htm,html&_method=GET | ||||||
|  | 
 | ||||||
|  | { "dirs": [ "old", "2013,12", "2013,11" ] } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ```javascript | ||||||
|  | { | ||||||
|  |   "posts/2015": [ { "name": ... }, { ... } ] | ||||||
|  | , "posts/2013": [ ... ] | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | /api/fs/files | ||||||
|  | ------------- | ||||||
|  | 
 | ||||||
|  | `GET http://local.dear.desi:8080/api/fs/files?path=posts/happy-new-year.md` | ||||||
|  | 
 | ||||||
|  | ```json | ||||||
|  | { "path": "posts/intro-to-http-with-netcat-node-connect.md" | ||||||
|  | , "lastModifiedDate": "2013-08-01T22:47:37.000Z" | ||||||
|  | , "contents": "..." | ||||||
|  | , "sha1": "6eae3a5b062c6d0d79f070c26e6d62486b40cb46" | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | To retrieve multiple files at once: | ||||||
|  | 
 | ||||||
|  | * for a few simple files without special chars just change `path` to `paths` and separate with commas | ||||||
|  | 
 | ||||||
|  | `GET http://local.dear.desi:8080/api/fs/files?paths=posts/foo.md,posts/bar.md` | ||||||
|  | 
 | ||||||
|  | * for many files, or files with special chars, `POST` an object containing an array of `pathss` with  `&_method=GET` appended to the url. | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | POST http://local.dear.desi:8080/api/fs/files?dotfiles=true&extensions=md,markdown,jade,htm,html&_method=GET | ||||||
|  | 
 | ||||||
|  | { "paths": [ "posts/foo.md", "posts/2013,11,30.md" ] } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ```json | ||||||
|  | [ | ||||||
|  |   { "path": "posts/foo.md" | ||||||
|  |   , "lastModifiedDate": "2013-08-01T22:47:37.000Z" | ||||||
|  |   , "contents": "..." | ||||||
|  |   , "sha1": "6eae3a5b062c6d0d79f070c26e6d62486b40cb46" | ||||||
|  |   } | ||||||
|  | , ... | ||||||
|  | ] | ||||||
|  | ``` | ||||||
|  | |||||||
| @ -2,15 +2,20 @@ | |||||||
| <html> | <html> | ||||||
|   <head> |   <head> | ||||||
|     <title>Dear Desi</title> |     <title>Dear Desi</title> | ||||||
|  |     <!-- Deps --> | ||||||
|     <script src="./bower_components/bluebird/js/browser/bluebird.js"></script> |     <script src="./bower_components/bluebird/js/browser/bluebird.js"></script> | ||||||
|     <script src="./bower_components/mustache/mustache.js"></script> |     <script src="./bower_components/mustache/mustache.js"></script> | ||||||
|     <script src="./bower_components/marked/lib/marked.js"></script> |     <script src="./bower_components/marked/lib/marked.js"></script> | ||||||
|     <script src="./bower_components/js-yaml/dist/js-yaml.js"></script> |     <script src="./bower_components/js-yaml/dist/js-yaml.js"></script> | ||||||
|     <script src="./bower_components/path/path.js"></script> |     <script src="./bower_components/path/path.js"></script> | ||||||
|  | 
 | ||||||
|  |     <!-- Libs --> | ||||||
|     <script src="./lib/deardesi-utils.js"></script> |     <script src="./lib/deardesi-utils.js"></script> | ||||||
|     <script src="./lib/verify-config.js"></script> |     <script src="./lib/verify-config.js"></script> | ||||||
|     <script src="./lib/deardesi-browser.js"></script> |     <script src="./lib/deardesi-browser.js"></script> | ||||||
|     <script src="./lib/frontmatter.js"></script> |     <script src="./lib/frontmatter.js"></script> | ||||||
|  | 
 | ||||||
|  |     <!-- Desi --> | ||||||
|     <script src="./deardesi.js"></script> |     <script src="./deardesi.js"></script> | ||||||
|   </head> |   </head> | ||||||
|   <body> |   <body> | ||||||
|  | |||||||
							
								
								
									
										162
									
								
								lib/fsapi.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								lib/fsapi.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,162 @@ | |||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | var PromiseA      = require('bluebird').Promise | ||||||
|  |   , fs            = PromiseA.promisifyAll(require('fs')) | ||||||
|  |   , forEachAsync  = require('foreachasync').forEachAsync | ||||||
|  |   , path          = require('path') | ||||||
|  |   , walk          = require('walk') | ||||||
|  |   , escapeRegExp  = require('./deardesi-utils').escapeRegExp | ||||||
|  |   , safeResolve   = require('./deardesi-utils').safeResolve | ||||||
|  |   , sha1sum       = function (str) { return require('secret-utils').hashsum('sha1', str); } | ||||||
|  |   ; | ||||||
|  | 
 | ||||||
|  | function strip(prefix, pathname) { | ||||||
|  |   return pathname.substr(prefix.length + 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function walkDir(parent, sub, opts) { | ||||||
|  |   opts = opts || {}; | ||||||
|  | 
 | ||||||
|  |   var prefix = path.resolve(parent) | ||||||
|  |     , trueRoot = path.resolve(prefix, sub) | ||||||
|  |     , files = [] | ||||||
|  |     ; | ||||||
|  | 
 | ||||||
|  |   function filter(name) { | ||||||
|  |     if (!name) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if ('.' === name[0] && !opts.dotfiles) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (opts.extensions && opts.extensions.length) { | ||||||
|  |       if (!opts.extensions.some(function (ext) { | ||||||
|  |         return new RegExp('\\.' + escapeRegExp(ext) + '$').test(name); | ||||||
|  |       })) { | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return new PromiseA(function (resolve) { | ||||||
|  |     var walker = walk.walk(trueRoot) | ||||||
|  |       ; | ||||||
|  | 
 | ||||||
|  |     walker.on('nodeError', function (filepath, stat, next) { | ||||||
|  |       //stats.forEach(function (stat) {
 | ||||||
|  |       if (!filter(stat.name)) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       stat.error.path = path.join(strip(prefix, filepath), stat.name); | ||||||
|  |       files.push({ | ||||||
|  |         name: stat.name | ||||||
|  |       , relativePath: strip(prefix, filepath) | ||||||
|  |       , type: undefined | ||||||
|  |       , error: stat.error | ||||||
|  |       }); | ||||||
|  |       //});
 | ||||||
|  | 
 | ||||||
|  |       next(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     walker.on('files', function (root, stats, next) { | ||||||
|  |       var dirname = strip(prefix, root) | ||||||
|  |         ; | ||||||
|  | 
 | ||||||
|  |       function eachFile(stat) { | ||||||
|  |         var file | ||||||
|  |           ; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         if (!filter(stat.name)) { | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         file = { | ||||||
|  |           name: stat.name | ||||||
|  |         , lastModifiedDate: stat.mtime.toISOString() | ||||||
|  |         , size: stat.size | ||||||
|  |         , relativePath: dirname | ||||||
|  |         , type: undefined // TODO include mimetype
 | ||||||
|  |         }; | ||||||
|  |         files.push(file); | ||||||
|  | 
 | ||||||
|  |         if (opts.contents) { | ||||||
|  |           return fs.readFileAsync(path.join(root, stat.name), 'utf8').then(function (contents) { | ||||||
|  |             file.contents = contents; | ||||||
|  |             file.sha1 = sha1sum(contents); | ||||||
|  |           }); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (!opts.contents) { | ||||||
|  |         stats.forEach(eachFile); | ||||||
|  |         next(); | ||||||
|  |       } else { | ||||||
|  |         forEachAsync(stats, eachFile).then(next); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     walker.on('end', function () { | ||||||
|  |       resolve(files); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function walkDirs(parent, subs, opts) { | ||||||
|  |   opts = opts || {}; | ||||||
|  | 
 | ||||||
|  |   var collections = {} | ||||||
|  |     ; | ||||||
|  | 
 | ||||||
|  |   return forEachAsync(subs, function (sub) { | ||||||
|  |     return walkDir(parent, sub, opts).then(function (results) { | ||||||
|  |       collections[sub] = results; | ||||||
|  |     }); | ||||||
|  |   }).then(function () { | ||||||
|  |     return collections; | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | function getfs(blogdir, filepaths) { | ||||||
|  |   var files = [] | ||||||
|  |     ; | ||||||
|  | 
 | ||||||
|  |   return forEachAsync(filepaths, function (filepath) { | ||||||
|  |     var pathname = safeResolve(blogdir, filepath) | ||||||
|  |       ; | ||||||
|  | 
 | ||||||
|  |     return fs.lstatAsync(pathname).then(function (stat) { | ||||||
|  |       return fs.readFileAsync(pathname, null).then(function (buffer) { | ||||||
|  |         files.push({ | ||||||
|  |           path: filepath | ||||||
|  |         , size: buffer.byteLength | ||||||
|  |         , lastModifiedDate: stat.mtime.toISOString() | ||||||
|  |         , contents: buffer.toString('utf8') | ||||||
|  |         , sha1: sha1sum(buffer) | ||||||
|  |         , type: undefined | ||||||
|  |         }); | ||||||
|  |       }); | ||||||
|  |     }).catch(function (e) { | ||||||
|  |       files.push({ path: filepath, error: e.message }); | ||||||
|  |     }); | ||||||
|  |   }).then(function () { | ||||||
|  |     return files; | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | /* | ||||||
|  | walkDirs('blog', ['posts'], { contents: false }).then(function (stats) { | ||||||
|  |   console.log(JSON.stringify(stats, null, '  ')); | ||||||
|  | }); | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | module.exports.walk = { walkDirs: walkDirs, walkDir: walkDir }; | ||||||
|  | module.exports.getfs = getfs; | ||||||
|  | module.exports.walkDir = walkDir; | ||||||
|  | module.exports.walkDirs = walkDirs; | ||||||
							
								
								
									
										173
									
								
								lib/walk.js
									
									
									
									
									
								
							
							
						
						
									
										173
									
								
								lib/walk.js
									
									
									
									
									
								
							| @ -1,173 +0,0 @@ | |||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| var PromiseA = require('bluebird').Promise |  | ||||||
|   , fs = PromiseA.promisifyAll(require('fs')) |  | ||||||
|   , forEachAsync = require('foreachasync').forEachAsync |  | ||||||
|   , path = require('path') |  | ||||||
|   , walk = require('walk') |  | ||||||
|   , walker |  | ||||||
|   ; |  | ||||||
| 
 |  | ||||||
| function strip(prefix, pathname) { |  | ||||||
|   return pathname.substr(prefix.length + 1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
| function walkDir(parent, sub, opts) { |  | ||||||
|   opts = opts || {}; |  | ||||||
| 
 |  | ||||||
|   var prefix = path.resolve(parent) |  | ||||||
|     , trueRoot = path.resolve(prefix, sub) |  | ||||||
|     , things = {} |  | ||||||
|     ; |  | ||||||
| 
 |  | ||||||
|   return fs.lstatAsync(trueRoot).then(function (stat) { |  | ||||||
|     var name = strip(prefix, trueRoot) |  | ||||||
|       ; |  | ||||||
| 
 |  | ||||||
|     things[name] = things[name] || {}; |  | ||||||
|     things[name].name = stat.name; |  | ||||||
|     things[name].lastModifiedDate = stat.mtime.toISOString(); |  | ||||||
|     things[name].contents = []; |  | ||||||
| 
 |  | ||||||
|     return new PromiseA(function (resolve) { |  | ||||||
|       walker = walk.walk(trueRoot); |  | ||||||
| 
 |  | ||||||
|       walker.on('directories', function (root, stats, next) { |  | ||||||
|         var dirname = strip(prefix, root) |  | ||||||
|           ; |  | ||||||
| 
 |  | ||||||
|         stats.forEach(function (stat) { |  | ||||||
|           var cdirname = path.join(dirname, stat.name) |  | ||||||
|             ; |  | ||||||
| 
 |  | ||||||
|           things[cdirname] = things[cdirname] || {}; |  | ||||||
|           things[cdirname].name = stat.name; |  | ||||||
|           things[cdirname].lastModifiedDate = stat.mtime.toISOString(); |  | ||||||
|           things[cdirname].contents = things[cdirname].contents || []; |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         next(); |  | ||||||
|       }); |  | ||||||
|       walker.on('directory', function (root, stat, next) { |  | ||||||
|         var dirname = strip(prefix, path.join(root, stat.name)) |  | ||||||
|           ; |  | ||||||
| 
 |  | ||||||
|         things[dirname] = things[dirname] || {}; |  | ||||||
|         things[dirname].name = stat.name; |  | ||||||
|         things[dirname].lastModifiedDate = stat.mtime.toISOString(); |  | ||||||
|         things[dirname].contents = things[dirname].contents || []; |  | ||||||
| 
 |  | ||||||
|         next(); |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|       walker.on('files', function (root, stats, next) { |  | ||||||
|         var dirname = strip(prefix, root) |  | ||||||
|           ; |  | ||||||
| 
 |  | ||||||
|         function eachFile(stat) { |  | ||||||
|           var file |  | ||||||
|             ; |  | ||||||
| 
 |  | ||||||
|           file = { |  | ||||||
|             name: stat.name |  | ||||||
|           , lastModifiedDate: stat.mtime.toISOString() |  | ||||||
|           }; |  | ||||||
| 
 |  | ||||||
|           things[dirname].contents.push(file); |  | ||||||
| 
 |  | ||||||
|           if (opts.contents) { |  | ||||||
|             return fs.readFileAsync(path.join(root, stat.name), 'utf8').then(function (contents) { |  | ||||||
|               file.contents = contents; |  | ||||||
|             }); |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (!opts.contents) { |  | ||||||
|           stats.forEach(eachFile); |  | ||||||
|           next(); |  | ||||||
|         } else { |  | ||||||
|           forEachAsync(stats, eachFile).then(next); |  | ||||||
|         } |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|       walker.on('end', function () { |  | ||||||
|         resolve(things); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| function walkDir(parent, sub, opts) { |  | ||||||
|   opts = opts || {}; |  | ||||||
| 
 |  | ||||||
|   var prefix = path.resolve(parent) |  | ||||||
|     , trueRoot = path.resolve(prefix, sub) |  | ||||||
|     , files = [] |  | ||||||
|     ; |  | ||||||
| 
 |  | ||||||
|   return new PromiseA(function (resolve) { |  | ||||||
|     walker = walk.walk(trueRoot); |  | ||||||
| 
 |  | ||||||
|     walker.on('files', function (root, stats, next) { |  | ||||||
|       var dirname = strip(prefix, root) |  | ||||||
|         ; |  | ||||||
| 
 |  | ||||||
|       function eachFile(stat) { |  | ||||||
|         var file |  | ||||||
|           ; |  | ||||||
| 
 |  | ||||||
|         file = { |  | ||||||
|           name: stat.name |  | ||||||
|         , lastModifiedDate: stat.mtime.toISOString() |  | ||||||
|         , size: stat.size |  | ||||||
|         , path: dirname |  | ||||||
|         }; |  | ||||||
|         files.push(file); |  | ||||||
| 
 |  | ||||||
|         if (opts.contents) { |  | ||||||
|           return fs.readFileAsync(path.join(root, stat.name), 'utf8').then(function (contents) { |  | ||||||
|             file.contents = contents; |  | ||||||
|           }); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (!opts.contents) { |  | ||||||
|         stats.forEach(eachFile); |  | ||||||
|         next(); |  | ||||||
|       } else { |  | ||||||
|         forEachAsync(stats, eachFile).then(next); |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     walker.on('end', function () { |  | ||||||
|       resolve(files); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function walkDirs(parent, subs, opts) { |  | ||||||
|   opts = opts || {}; |  | ||||||
| 
 |  | ||||||
|   var collections = {} |  | ||||||
|     ; |  | ||||||
| 
 |  | ||||||
|   return forEachAsync(subs, function (sub) { |  | ||||||
|     return walkDir(parent, sub, opts).then(function (results) { |  | ||||||
|       collections[sub] = results; |  | ||||||
|     }); |  | ||||||
|   }).then(function () { |  | ||||||
|     return collections; |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
| walkDirs('blog', ['posts'], { contents: false }).then(function (stats) { |  | ||||||
|   console.log(JSON.stringify(stats, null, '  ')); |  | ||||||
| }); |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| module.exports.walkDir = walkDir; |  | ||||||
| module.exports.walkDirs = walkDirs; |  | ||||||
| @ -45,7 +45,7 @@ | |||||||
|     "require-yamljs": "^1.0.1", |     "require-yamljs": "^1.0.1", | ||||||
|     "secret-utils": "^1.0.2", |     "secret-utils": "^1.0.2", | ||||||
|     "serve-static": "^1.7.2", |     "serve-static": "^1.7.2", | ||||||
|     "walk": "^2.3.5", |     "walk": "^2.3.9", | ||||||
|     "yaml": "^0.2.3", |     "yaml": "^0.2.3", | ||||||
|     "yamljs": "^0.2.1" |     "yamljs": "^0.2.1" | ||||||
|   } |   } | ||||||
|  | |||||||
							
								
								
									
										88
									
								
								server.js
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								server.js
									
									
									
									
									
								
							| @ -2,23 +2,20 @@ | |||||||
| 
 | 
 | ||||||
| require('require-yaml'); | require('require-yaml'); | ||||||
| 
 | 
 | ||||||
| var PromiseA = require('bluebird').Promise | var connect     = require('connect') | ||||||
|   , connect = require('connect') |   //, PromiseA  = require('bluebird').Promise
 | ||||||
|   , query = require('connect-query') |   , query       = require('connect-query') | ||||||
|   , bodyParser = require('body-parser') |   , bodyParser  = require('body-parser') | ||||||
|   , serveStatic = require('serve-static') |   , serveStatic = require('serve-static') | ||||||
|   , forEachAsync = require('foreachasync').forEachAsync |   , send        = require('connect-send-json') | ||||||
|   , send = require('connect-send-json') |  | ||||||
| 
 | 
 | ||||||
|   , app = connect() |   , app         = connect() | ||||||
|   , walk = require('./lib/walk') |   , walk        = require('./lib/fsapi').walk | ||||||
|  |   , getfs       = require('./lib/fsapi').getfs | ||||||
| 
 | 
 | ||||||
|   , config = require('./config.yml') |   , config      = require('./config.yml') | ||||||
|   , safeResolve = require('./lib/deardesi-utils').safeResolve |   , path        = require('path') | ||||||
|   , path = require('path') |   , blogdir     = path.resolve(config.blogdir || __dirname) | ||||||
|   , blogdir = path.resolve(config.blogdir || __dirname) |  | ||||||
|   , sha1sum = function (str) { return require('secret-utils').hashsum('sha1', str); } |  | ||||||
|   , fs = PromiseA.promisifyAll(require('fs')) |  | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -33,54 +30,57 @@ app | |||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       var filepaths = req.query.path && [req.query.path] || req.body.paths |       var filepaths = req.query.path && [req.query.path] || (req.query.paths && req.query.paths.split(/,/g)) || req.body.paths | ||||||
|         , files = [] |  | ||||||
|         ; |         ; | ||||||
| 
 | 
 | ||||||
|       if (!filepaths || !filepaths.length) { |       if (!filepaths || !filepaths.length) { | ||||||
|         res.json({ error: "please specify req.query.path or req.body.paths" }); |         res.json({ error: "please specify GET w/ req.query.path or POST _method=GET&paths=path/to/thing,..." }); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       return forEachAsync(filepaths, function (filepath) { |       return getfs(blogdir, filepaths).then(function (files) { | ||||||
|         var pathname = safeResolve(blogdir, filepath) |         if (!req.body.paths && !req.query.paths) { | ||||||
|           ; |           res.json(files[0]); | ||||||
| 
 |         } else { | ||||||
|         return fs.lstatAsync(pathname).then(function (stat) { |           res.send(files); | ||||||
|           return fs.readFileAsync(pathname, null).then(function (buffer) { |         } | ||||||
|             files.push({ |  | ||||||
|               path: filepath |  | ||||||
|             , size: buffer.byteLength |  | ||||||
|             , lastModifiedDate: stat.mtime.toISOString() |  | ||||||
|             , contents: buffer.toString('utf8') |  | ||||||
|             , sha1: sha1sum(buffer) |  | ||||||
|             ,  |  | ||||||
|             }); |  | ||||||
|           }); |  | ||||||
|         }).catch(function (e) { |  | ||||||
|           files.push({ path: filepath, error: e.message }); |  | ||||||
|         }); |  | ||||||
|       }).then(function () { |  | ||||||
|         res.send(files); |  | ||||||
|       }); |       }); | ||||||
|     }) |     }) | ||||||
| 
 | 
 | ||||||
|   .use('/api/fs/walk', function (req, res, next) { |   .use('/api/fs/walk', function (req, res, next) { | ||||||
|  |       var opts = {} | ||||||
|  |         ; | ||||||
|  | 
 | ||||||
|       if (!(/^GET$/i.test(req.method) || /^GET$/i.test(req.query._method))) { |       if (!(/^GET$/i.test(req.method) || /^GET$/i.test(req.query._method))) { | ||||||
|         next(); |         next(); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       var dirnames = req.query.dir && [req.query.dir] || req.body.dirs |       var dirnames = req.query.dir && [req.query.dir] || (req.query.dirs && req.query.dirs.split(/,/g)) || req.body.dirs | ||||||
|         ; |         ; | ||||||
| 
 | 
 | ||||||
|       if (!dirnames || !dirnames.length) { |       if (!dirnames || !dirnames.length) { | ||||||
|         res.json({ error: "please specify req.query.dir or req.body.dirs" }); |         res.json({ error: "please specify GET w/ req.query.dir or POST w/ _method=GET&dirs=path/to/thing,..." }); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       walk.walkDirs(blogdir, dirnames, { contents: false }).then(function (stats) { |       /* | ||||||
|         if (!req.body.dirs) { |       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; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // TODO opts.contents?
 | ||||||
|  |       walk.walkDirs(blogdir, dirnames, opts).then(function (stats) { | ||||||
|  |         if (!req.body.dirs && !req.query.dirs) { | ||||||
|           res.json(stats[dirnames[0]]); |           res.json(stats[dirnames[0]]); | ||||||
|         } else { |         } else { | ||||||
|           res.json(stats); |           res.json(stats); | ||||||
| @ -92,11 +92,13 @@ app | |||||||
|       next(); |       next(); | ||||||
|       return; |       return; | ||||||
|     }) |     }) | ||||||
|  |   .use('/api/fs/static', serveStatic('.')) | ||||||
|  | 
 | ||||||
|   .use(serveStatic('.')) |   .use(serveStatic('.')) | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| module.exports = app; | module.exports = app; | ||||||
| 
 | 
 | ||||||
| require('http').createServer(app).listen(8080, function () { | require('http').createServer().on('request', app).listen(80, function () { | ||||||
|   console.log('listening 8080'); |   console.log('listening 80'); | ||||||
| }); | }); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user