configuration.coffee | |
|---|---|
| The | fs = require "fs"
path = require "path"
async = require "async"
Logger = require "./logger"
{mkdirp} = require "./util"
{sourceScriptEnv} = require "./util"
{getUserEnv} = require "./util"
module.exports = class Configuration |
| The user configuration file,
See the | @userConfigurationPath: path.join process.env.HOME, ".powconfig" |
| Evaluates the user configuration script and calls the | @loadUserConfigurationEnvironment: (callback) ->
getUserEnv (err, env) =>
if err
callback err
else
path.exists p = @userConfigurationPath, (exists) ->
if exists
sourceScriptEnv p, env, callback
else
callback null, env |
| Creates a Configuration object after evaluating the user
configuration file. Any environment variables in | @getUserConfiguration: (callback) ->
@loadUserConfigurationEnvironment (err, env) ->
if err
callback err
else
callback null, new Configuration env |
| A list of option names accessible on | @optionNames: [
"bin", "dstPort", "httpPort", "dnsPort", "timeout", "workers",
"domains", "extDomains", "hostRoot", "logRoot", "rvmPath"
] |
| Pass in any environment variables you'd like to override when
creating a | constructor: (env = process.env) ->
@loggers = {}
@initialize env |
| Valid environment variables and their defaults: | initialize: (@env) -> |
|
| @bin = env.POW_BIN ? path.join __dirname, "../bin/pow" |
|
| @dstPort = env.POW_DST_PORT ? 80 |
|
| @httpPort = env.POW_HTTP_PORT ? 20559 |
|
| @dnsPort = env.POW_DNS_PORT ? 20560 |
|
| @timeout = env.POW_TIMEOUT ? 15 * 60 |
|
| @workers = env.POW_WORKERS ? 2 |
|
| @domains = env.POW_DOMAINS ? env.POW_DOMAIN ? "dev" |
|
| @extDomains = env.POW_EXT_DOMAINS ? [] |
| Allow for comma-separated domain lists, e.g. | @domains = @domains.split?(",") ? @domains
@extDomains = @extDomains.split?(",") ? @extDomains
@allDomains = @domains.concat @extDomains |
| Support *.xip.io top-level domains. | @allDomains.push /\d+\.\d+\.\d+\.\d+\.xip\.io$/, /[0-9a-z]{1,7}\.xip\.io$/ |
| Runtime support files live in | @supportRoot = libraryPath "Application Support", "Pow" |
|
| @hostRoot = env.POW_HOST_ROOT ? path.join @supportRoot, "Hosts" |
|
| @logRoot = env.POW_LOG_ROOT ? libraryPath "Logs", "Pow" |
|
| @rvmPath = env.POW_RVM_PATH ? path.join process.env.HOME, ".rvm/scripts/rvm" |
| Precompile regular expressions for matching domain names to be served by the DNS server and hosts to be served by the HTTP server. | @dnsDomainPattern = compilePattern @domains
@httpDomainPattern = compilePattern @allDomains |
| Gets an object of the | toJSON: ->
result = {}
result[key] = @[key] for key in @constructor.optionNames
result |
| Retrieve a | getLogger: (name) ->
@loggers[name] ||= new Logger path.join @logRoot, name + ".log" |
| Globally disable or enable RVM deprecation notices by touching or
removing the | disableRvmDeprecationNotices: ->
fs.writeFile path.join(@supportRoot, ".disableRvmDeprecationNotices"), ""
enableRvmDeprecationNotices: ->
fs.unlink path.join @supportRoot, ".disableRvmDeprecationNotices" |
| Search | findHostConfiguration: (host = "", callback) ->
@gatherHostConfigurations (err, hosts) =>
return callback err if err
for domain in @allDomains
for file in getFilenamesForHost host, domain
if config = hosts[file]
return callback null, domain, config
if config = hosts["default"]
return callback null, @allDomains[0], config
callback null |
| Asynchronously build a mapping of entries in The mapping object will look something like this: | gatherHostConfigurations: (callback) ->
hosts = {}
mkdirp @hostRoot, (err) =>
return callback err if err
fs.readdir @hostRoot, (err, files) =>
return callback err if err
async.forEach files, (file, next) =>
root = path.join @hostRoot, file
name = file.toLowerCase()
rstat root, (err, stats, path) ->
if stats?.isDirectory()
hosts[name] = root: path
next()
else if stats?.isFile()
fs.readFile path, 'utf-8', (err, data) ->
return next() if err
data = data.trim()
if data.length < 10 and not isNaN(parseInt(data))
hosts[name] = {url: "http://localhost:#{parseInt(data)}"}
else if data.match("https?://")
hosts[name] = {url: data}
next()
else
next()
, (err) ->
callback err, hosts |
| Convenience wrapper for constructing paths to subdirectories of
| libraryPath = (args...) ->
path.join process.env.HOME, "Library", args... |
| Strip a trailing | getFilenamesForHost = (host, domain) ->
host = host.toLowerCase()
domain = host.match(domain)?[0] ? "" if domain.test?
if host.slice(-domain.length - 1) is ".#{domain}"
parts = host.slice(0, -domain.length - 1).split "."
length = parts.length
for i in [0...length]
parts.slice(i, length).join "."
else
[] |
| Similar to | rstat = (path, callback) ->
fs.lstat path, (err, stats) ->
if err
callback err
else if stats?.isSymbolicLink()
fs.realpath path, (err, realpath) ->
if err then callback err
else rstat realpath, callback
else
callback err, stats, path |
| Helper function for compiling a list of top-level domains into a regular expression for matching purposes. | compilePattern = (domains) ->
/// ( (^|\.) (#{domains.join("|")}) ) \.? $ ///i
|