Repository: hoodiehq/hoodie
Pull request #678 (2017-01-23 20:13:09)

assure data folders
We currently assure the folders in `@hoodie/server`, but the correct place for it is in `hoodie/cli`. Part of hoodiehq/hoodie-server#532

gr2m: I’ve tested it locally extensively. This is fixing deployment to know which several folks are waiting for, so going ahead and merge it. But if you find anything let me know and I’ll create follow up issues / PRs

Patch:
diff --git a/cli/assure-folders.js b/cli/assure-folders.js
new file mode 100644
index 00000000..e998c47c
--- /dev/null
+++ b/cli/assure-folders.js
@@ -0,0 +1,22 @@
+module.exports = assureFolders
+
+var path = require('path')
+var mkdirp = require('mkdirp')
+var parallel = require('async').parallel
+
+function assureFolders (options, callback) {
+  if (options.inMemory) {
+    return callback()
+  }
+
+  var tasks = [
+    mkdirp.bind(null, options.data)
+  ]
+
+  if (!options.dbUrl) {
+    var storeFilesPath = path.join(options.data, 'data') + path.sep
+    tasks.push(mkdirp.bind(null, storeFilesPath))
+  }
+
+  parallel(tasks, callback)
+}
diff --git a/cli/index.js b/cli/index.js
index d538d3f8..477d2e34 100644
--- a/cli/index.js
+++ b/cli/index.js
@@ -3,6 +3,7 @@ module.exports = run
 var log = require('npmlog')
 var Hapi = require('hapi')
 
+var assureFolders = require('./assure-folders')
 var compatibilityCheck = require('./compatibility-check.js')
 var getOptions = require('./options')
 var getHapiOptions = require('./hapi-options')
@@ -20,23 +21,30 @@ function run (callback) {
     var projectPath = process.cwd()
     var options = getOptions(projectPath)
 
-    log.level = options.loglevel || 'warn'
+    log.level = options.loglevel
     log.verbose('app', 'Initialising')
 
-    var hapiOptions = getHapiOptions(options)
-    var server = new Hapi.Server(hapiOptions.server)
-    server.connection(hapiOptions.connection)
-
-    server.register({
-      register: hoodie,
-      options: parseOptions(options)
-    }, function (error) {
+    assureFolders(options, function (error) {
       if (error) {
+        log.error('app', error.message)
         return callback(error)
       }
 
-      server.start(function (error) {
-        callback(error, server)
+      var hapiOptions = getHapiOptions(options)
+      var server = new Hapi.Server(hapiOptions.server)
+      server.connection(hapiOptions.connection)
+
+      server.register({
+        register: hoodie,
+        options: parseOptions(options)
+      }, function (error) {
+        if (error) {
+          return callback(error)
+        }
+
+        server.start(function (error) {
+          callback(error, server)
+        })
       })
     })
   })
diff --git a/cli/parse-options.js b/cli/parse-options.js
index 9b605a09..08d6340b 100644
--- a/cli/parse-options.js
+++ b/cli/parse-options.js
@@ -1,6 +1,7 @@
 module.exports = parseOptions
 
 var log = require('npmlog')
+var path = require('path')
 var PouchDB = require('pouchdb-core')
 var urlParse = require('url').parse
 
@@ -59,7 +60,7 @@ function parseOptions (options) {
     log.info('config', 'Storing all data in memory only')
   } else {
     PouchDB.plugin(require(options.dbAdapter))
-    dbOptions.prefix = config.paths.data + '/data/'
+    dbOptions.prefix = path.join(config.paths.data, 'data') + path.sep
     log.info('config', 'Storing all data in ' + dbOptions.prefix + ' using ' + options.dbAdapter)
   }
   config.PouchDB = PouchDB.defaults(dbOptions)
diff --git a/package.json b/package.json
index c1c3ddc7..f06e7b20 100644
--- a/package.json
+++ b/package.json
@@ -23,6 +23,7 @@
     "hapi-cors-headers": "^1.0.0",
     "inert": "^4.0.0",
     "lodash": "^4.11.2",
+    "mkdirp": "^0.5.1",
     "node-emoji": "^1.3.0",
     "npmlog": "^4.0.0",
     "pouchdb-adapter-fs": "^2.0.5",


Test patch:
diff --git a/test/unit/cli/assure-folders-test.js b/test/unit/cli/assure-folders-test.js
new file mode 100644
index 00000000..93903558
--- /dev/null
+++ b/test/unit/cli/assure-folders-test.js
@@ -0,0 +1,65 @@
+var proxyquire = require('proxyquire').noCallThru()
+var simple = require('simple-mock')
+var test = require('tap').test
+
+var pathMock = {
+  sep: '--sep--',
+  join: function () { return 'joined-path' }
+}
+
+test('assure folders', function (group) {
+  group.test('default settings', function (t) {
+    var mkdirpMock = simple.stub().callbackWith(null)
+    var assureFolders = proxyquire('../../../cli/assure-folders', {
+      'path': pathMock,
+      'mkdirp': mkdirpMock
+    })
+    assureFolders({
+      data: 'data'
+    }, function (error) {
+      t.error(error)
+
+      t.is(mkdirpMock.callCount, 2, 'created two folders')
+      t.is(mkdirpMock.calls[0].arg, 'data')
+      t.is(mkdirpMock.calls[1].arg, 'joined-path--sep--')
+
+      t.end()
+    })
+  })
+
+  group.test('inMemory', function (t) {
+    var mkdirpMock = simple.stub().callbackWith(null)
+    var assureFolders = proxyquire('../../../cli/assure-folders', {
+      'path': pathMock,
+      'mkdirp': mkdirpMock
+    })
+    assureFolders({
+      inMemory: true
+    }, function (error) {
+      t.error(error)
+
+      t.is(mkdirpMock.callCount, 0, 'no folders created')
+
+      t.end()
+    })
+  })
+
+  group.test('dbUrl', function (t) {
+    var mkdirpMock = simple.stub().callbackWith(null)
+    var assureFolders = proxyquire('../../../cli/assure-folders', {
+      'path': pathMock,
+      'mkdirp': mkdirpMock
+    })
+    assureFolders({
+      dbUrl: 'http://example.com'
+    }, function (error) {
+      t.error(error)
+
+      t.is(mkdirpMock.callCount, 1, 'one created')
+
+      t.end()
+    })
+  })
+
+  group.end()
+})
diff --git a/test/unit/cli/parse-options-test.js b/test/unit/cli/parse-options-test.js
index 6b38b0dd..ef9bd90b 100644
--- a/test/unit/cli/parse-options-test.js
+++ b/test/unit/cli/parse-options-test.js
@@ -27,6 +27,7 @@ var parseOptions = proxyquire('../../../cli/parse-options', {
 test('parse options', function (group) {
   group.test('unset keys', function (t) {
     var config = parseOptions({
+      data: '.hoodie',
       dbAdapter: 'pouchdb-adapter-fs'
     })