From e0af8c6c6ad186418f9f54ba983661465bf041cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Greg=20Berg=C3=A9?= <berge.greg@gmail.com>
Date: Tue, 13 Feb 2018 00:24:14 +0100
Subject: [PATCH] feat: improve scripts

- Support password
- Handle custom Docker service name
---
 src/cli.js    |  9 +++++++--
 src/create.js | 23 +++++++++++------------
 src/drop.js   | 26 +++++++++++++-------------
 src/dump.js   | 33 ++++++++++++++++-----------------
 src/load.js   | 23 ++++++++++++-----------
 src/utils.js  | 37 +++++++++++++++++++++++++++++++++++++
 6 files changed, 96 insertions(+), 55 deletions(-)

diff --git a/src/cli.js b/src/cli.js
index d6daa8a..01fa797 100644
--- a/src/cli.js
+++ b/src/cli.js
@@ -82,9 +82,13 @@ function initConfig(env) {
     structurePath: knexScriptsConfig.structurePath || 'db/structure.sql',
     migrationsPath: join(process.cwd(), 'migrations'),
     docker:
-      commander.docker !== undefined
+      (commander.docker !== undefined
         ? commander.docker
-        : knexScriptsConfig.docker,
+        : knexScriptsConfig.docker) || false,
+    dockerService:
+      (commander.dockerService !== undefined
+        ? commander.dockerService
+        : knexScriptsConfig.docker) || 'postgres',
   }
 }
 
@@ -95,6 +99,7 @@ function invoke(env) {
         chalk`{blue Knex version: {green ${env.modulePackage.version}}}\n`,
     )
     .option('--docker', 'Use docker.')
+    .option('--docker-service', 'Docker service name.')
     .option('--knexfile [path]', 'Specify the knexfile path.')
     .option('--cwd [path]', 'Specify the working directory.')
     .option(
diff --git a/src/create.js b/src/create.js
index 98ad92e..888336e 100644
--- a/src/create.js
+++ b/src/create.js
@@ -1,19 +1,18 @@
 /* eslint-disable max-len */
 import { exec } from 'mz/child_process'
-import { preventEnv } from './utils'
+import {
+  preventEnv,
+  wrapDockerCommand,
+  getCommand,
+  getCommandEnv,
+} from './utils'
 
-async function create({ docker, env, knexConfig }) {
-  preventEnv('production', env)
+async function create(options) {
+  preventEnv('production', options.env)
 
-  const command = docker
-    ? `docker-compose run postgres createdb --host postgres --username ${
-        knexConfig.connection.user
-      } ${knexConfig.connection.database}`
-    : `createdb --username ${knexConfig.connection.user} ${
-        knexConfig.connection.database
-      }`
-
-  return exec(command)
+  const env = getCommandEnv(options)
+  const command = getCommand(options, 'createdb')
+  return exec(wrapDockerCommand(options, command), { env })
 }
 
 export default create
diff --git a/src/drop.js b/src/drop.js
index 4e0106c..d0ea1c8 100644
--- a/src/drop.js
+++ b/src/drop.js
@@ -1,18 +1,18 @@
+/* eslint-disable max-len */
 import { exec } from 'mz/child_process'
-import { preventEnv } from './utils'
+import {
+  preventEnv,
+  wrapDockerCommand,
+  getCommand,
+  getCommandEnv,
+} from './utils'
 
-async function drop({ docker, env, knexConfig }) {
-  preventEnv('production', env)
+async function create(options) {
+  preventEnv('production', options.env)
 
-  const command = docker
-    ? `docker-compose run postgres dropdb --host postgres --username ${
-        knexConfig.connection.user
-      } ${knexConfig.connection.database} --if-exists`
-    : `dropdb --username ${knexConfig.connection.user} ${
-        knexConfig.connection.database
-      } --if-exists`
-
-  return exec(command)
+  const env = getCommandEnv(options)
+  const command = getCommand(options, 'dropdb --if-exists')
+  return exec(wrapDockerCommand(options, command), { env })
 }
 
-export default drop
+export default create
diff --git a/src/dump.js b/src/dump.js
index 77ecebf..d68aeee 100644
--- a/src/dump.js
+++ b/src/dump.js
@@ -2,7 +2,12 @@ import { exec } from 'mz/child_process'
 import { appendFile, readdir, exists } from 'mz/fs'
 import { dirname } from 'path'
 import mkdirp from 'mkdirp'
-import { requireEnv } from './utils'
+import {
+  requireEnv,
+  wrapDockerCommand,
+  getCommand,
+  getCommandEnv,
+} from './utils'
 
 async function getMigrationInserts({ migrationsPath }) {
   if (!await exists(migrationsPath)) return ''
@@ -15,26 +20,20 @@ async function getMigrationInserts({ migrationsPath }) {
     .join('')
 }
 
-async function dump({
-  docker,
-  env,
-  structurePath,
-  migrationsPath,
-  knexConfig,
-}) {
-  requireEnv('development', env)
+async function dump(options) {
+  const { structurePath, migrationsPath } = options
+  requireEnv('development', options.env)
 
   mkdirp.sync(dirname(structurePath))
 
-  const command = docker
-    ? `docker-compose exec postgres pg_dump --schema-only --username ${
-        knexConfig.connection.user
-      } ${knexConfig.connection.database} > ${structurePath}`
-    : `pg_dump --schema-only --username ${knexConfig.connection.user} ${
-        knexConfig.connection.database
-      } > ${structurePath}`
+  const env = getCommandEnv(options)
+  const command = `${getCommand(
+    options,
+    'pg_dump --schema-only',
+  )} > ${structurePath}`
+
+  await exec(wrapDockerCommand(options, command), { env })
 
-  await exec(command)
   const migrationInserts = await getMigrationInserts({ migrationsPath })
   return appendFile(structurePath, `-- Knex migrations\n\n${migrationInserts}`)
 }
diff --git a/src/load.js b/src/load.js
index 6291ad7..e2eb78d 100644
--- a/src/load.js
+++ b/src/load.js
@@ -1,19 +1,20 @@
 /* eslint-disable max-len */
 import { exec } from 'mz/child_process'
-import { preventEnv } from './utils'
+import {
+  preventEnv,
+  wrapDockerCommand,
+  getCommand,
+  getCommandEnv,
+} from './utils'
 
-async function load({ env, docker, structurePath, knexConfig }) {
-  preventEnv('production', env)
+async function load(options) {
+  const { structurePath } = options
+  preventEnv('production', options.env)
 
-  const command = docker
-    ? `docker exec -i \`docker-compose ps -q postgres\` psql --username ${
-        knexConfig.connection.user
-      } ${knexConfig.connection.database} < ${structurePath}`
-    : `psql -h localhost --username ${knexConfig.connection.user} ${
-        knexConfig.connection.database
-      } < ${structurePath}`
+  const env = getCommandEnv(options)
+  const command = `${getCommand(options, 'psql')} < ${structurePath}`
 
-  return exec(command)
+  return exec(wrapDockerCommand(options, command), { env })
 }
 
 export default load
diff --git a/src/utils.js b/src/utils.js
index f6bb1b7..420efeb 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -9,3 +9,40 @@ export function requireEnv(requiredEnv, env) {
     throw new Error(`Only in ${requiredEnv} please!`)
   }
 }
+
+export function wrapDockerCommand(options, command) {
+  if (options.docker) {
+    return `docker-compose run ${options.dockerService} ${command}`
+  }
+
+  return command
+}
+
+export function getCommandEnv(options) {
+  if (options.knexConfig.password) {
+    return {
+      ...process.env,
+      PGPASSWORD: options.knexConfig.password,
+    }
+  }
+
+  return process.env
+}
+
+export function getCommand({ docker, knexConfig: { connection } }, command) {
+  const args = [command]
+
+  if (docker) {
+    args.push('--host postgres')
+  } else if (connection.host) {
+    args.push(`--host "${connection.host}"`)
+  }
+
+  if (connection.user) {
+    args.push(`--username "${connection.user}"`)
+  }
+
+  args.push(connection.database)
+
+  return args.join(' ')
+}