** (Service) - Holds the 'environment' with some handy utility methods.
**
** Although a 'mixin', implementations may still be created with the following:
**
** syntax: fantom
** iocEnv := IocEnv()
**
** Or pass in an override:
**
** syntax: fantom
** iocEnv := IocEnv("prod")
**
@Js
const mixin IocEnv {
** Returns the environment Str.
abstract Str env()
** Returns 'true' if the environment is 'prod', 'production' or *undefined*.
abstract Bool isProd()
** Returns 'true' if the environment is 'test' or 'testing'.
abstract Bool isStage()
** Returns 'true' if the environment is 'test' or 'testing'.
abstract Bool isTest()
** Returns 'true' if the environment is 'dev' or 'development'.
abstract Bool isDev()
** Returns 'true' if the environment matches the given 'env' in a case insensitive match.
abstract Bool isEnv(Str env)
** Logs environment to info.
abstract Void logToInfo()
** Returns the environment in abbreviated form; 'dev, test, prod'. Or just the env in lowercase if not recognised.
abstract Str abbr()
** Create an 'IocEnv' with the given (optional) environment override. This may be invoked via the ctor syntax:
**
** iocEnv := IocEnv("prod")
static new fromStr(Str? environmentOverride := null) {
IocEnvImpl(environmentOverride)
}
}
@Js
internal const class IocEnvImpl : IocEnv {
private static const Log log := IocEnv#.pod.log
override const Str env
override const Bool isProd
override const Bool isStage
override const Bool isTest
override const Bool isDev
const Str[] debug
const Str? overRIDE
new make(Str? overRIDE, |This|? f := null) {
debug := [,]
this.overRIDE = overRIDE
this.env = findEnv(debug, Env.cur.vars, `config.props`.toFile, Env.cur.args, overRIDE)
this.debug = debug
this.isProd = "production" .equalsIgnoreCase(env) || "prod" .equalsIgnoreCase(env)
this.isStage = "staging" .equalsIgnoreCase(env) || "stage".equalsIgnoreCase(env)
this.isTest = "testing" .equalsIgnoreCase(env) || "test" .equalsIgnoreCase(env)
this.isDev = "development" .equalsIgnoreCase(env) || "dev" .equalsIgnoreCase(env)
// not currently use for anything - but it's a nice get out of jail card
f?.call(this)
}
override Bool isEnv(Str env) {
this.env.equalsIgnoreCase(env)
}
override Void logToInfo() {
debug.each { log.info(it) }
}
override Str abbr() {
if (isProd) return "prod"
if (isStage) return "stage"
if (isTest) return "test"
if (isDev) return "dev"
return env.lower
}
override Str toStr() {
env
}
static Str findEnv(Str[] debug, Str:Str vars, File? config, Str[] args, Str? overRIDE) {
env := (Str?) null
if (vars.containsKey("env")) {
env = vars["env"]
addDebug(debug, "environment variable", "env", env)
}
if (vars.containsKey("environment")) {
env = vars["environment"]
addDebug(debug, "environment variable", "environment", env)
}
if (config != null && config.exists) {
try {
configProps := Str:Str[:] { it.caseInsensitive = true }.addAll(config.readProps)
if (configProps.containsKey("env")) {
env = configProps["env"]
addDebug(debug, config.name, "env", env)
}
if (configProps.containsKey("environment")) {
env = configProps["environment"]
addDebug(debug, config.name, "environment", env)
}
} catch (Err err)
log.warn(err.msg)
}
if (args.contains("-env")) {
index := args.index("-env")
if (args.size > (index+1)) {
env = args.get(index + 1)
addDebug(debug, "cmd line argument", "-env", env)
}
}
if (args.contains("-environment")) {
index := args.index("-environment")
if (args.size > (index+1)) {
env = args.get(index + 1)
addDebug(debug, "cmd line argument", "-environment", env)
}
}
if (overRIDE != null) {
env = overRIDE
addDebug(debug, "manual", "override", env)
}
if (env == null || env.isEmpty) {
env = "PRODUCTION"
debug.add("Environment has not been configured. Defaulting to 'PRODUCTION'")
}
return env
}
private static Void addDebug(Str[] debug, Str from, Str name, Str env) {
// Setting from environment variable 'env' : dev
// Overriding from cmd line argument 'env' : TEST
msg := (debug.isEmpty ? "Setting" : "Overriding") + " from ${from} '${name}' : ${env}"
debug.add(msg)
}
}