huxley-cli
Version:
CLI for Huxley Deployment Platform
110 lines (91 loc) • 3.77 kB
text/coffeescript
#===============================================================================
# Huxley - CLI Helpers
#===============================================================================
# This file specifies some handy helper methods.
{resolve, join} = require "path"
{async, read, merge, exists, mkdir, has, deep_equal} = require "fairmont"
Configurator = require "panda-config"
#--------------------
# Exposed Methods
#--------------------
module.exports =
# Prepare a basic error object to return to the UI.
build_error: (message, value) ->
return {
message: message
value: value
}
# Use until Fairmont bug is repaired.
empty: (x) -> x.length == 0
# Output an Info Blurb and optional message.
usage: async (entry, message) ->
docs = yield read( resolve( __dirname, "..", "docs", entry ) )
if message?
throw "#{message}\n" + docs
else
throw docs
# Sometimes we don't care if a promise is rejected, we just need to wait for it to be done one way
# or another. This function accepts an input promise but always resolves.
force: async (f, args...) ->
try
yield f args...
catch e
null
# Make a directory at the specified path, but throw an exception if that directory already exists.
safe_mkdir: async (path, mode) ->
unless yield exists path
mode ||= "0777"
yield mkdir mode, path
else
throw "Error: #{path} already exists. \n"
# In Huxley, configuration data is stored in multiple places. This function focuses on
# two levels of configuartion.
# (1) The first is the user's home configuration, located in the huxley dotfile
# within their $HOME directory (holds persistent data attached to their account).
# (2) The second is the application-level configuration, located in the repo's huxley
# manifest file. TODO: Currently, we only look in the execution path, so we require the
# CLI to be run in the repo's root directory. This should use an env variable like Node and git.
pull_configuration: async () ->
if yield exists join process.env.HOME, ".huxley"
# Load the configuration from the $HOME directory.
constructor = Configurator.make
prefix: "."
format: "yaml"
paths: [ process.env.HOME ]
home_config = constructor.make name: "huxley"
yield home_config.load()
else
throw "You must establish a dotfile configuration in your $HOME directory, ~/.huxley"
if yield exists join process.cwd(), "huxley.yaml"
# Load the application level configuration.
constructor = Configurator.make
extension: ".yaml"
format: "yaml"
paths: [ process.cwd() ]
app_config = constructor.make name: "huxley"
yield app_config.load()
# Create an object that is the union of the two configurations. Huxley observes
# configuration scope, so application configuration will override values set in the home-configuration.
if app_config?
config = merge home_config.data, app_config.data
else
config = home_config.data
# Return an object we can use to make requests, but also return the panda-config instances
# in case we need to save something.
return {
config: config
home_config: home_config
app_config: app_config if app_config?
}
# Nifty function that returns an array of objects when given an array of
# objects and an object subset to search for.
where: async (array, query) ->
final = []
for obj in array
count = 0
for key of query
break unless yield has key, obj
break unless yield deep_equal obj[key], query[key]
count++
final.push obj if count == Object.keys(query).length
return final