2019-06-15 20:20:04 +00:00
|
|
|
import { isNil, isString } from 'lodash';
|
|
|
|
import { join } from 'path';
|
|
|
|
|
2019-06-16 21:35:18 +00:00
|
|
|
import { CONFIG_ENV, CONFIG_SCHEMA } from 'src/config/schema';
|
|
|
|
import { includeSchema } from 'src/config/type/Include';
|
2019-06-15 20:20:04 +00:00
|
|
|
import { NotFoundError } from 'src/error/NotFoundError';
|
2019-06-16 21:15:01 +00:00
|
|
|
import { YamlParser } from 'src/parser/YamlParser';
|
2019-06-16 18:30:04 +00:00
|
|
|
import { readFileSync } from 'src/source';
|
2019-06-15 20:20:04 +00:00
|
|
|
|
|
|
|
includeSchema.schema = CONFIG_SCHEMA;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* With the given name, generate all potential config paths in their complete, absolute form.
|
|
|
|
*
|
2019-06-15 22:38:05 +00:00
|
|
|
* This will include the value of `SALTY_HOME`, `HOME`, the current working directory, and any extra paths
|
2019-06-15 20:20:04 +00:00
|
|
|
* passed as the final arguments.
|
|
|
|
*/
|
|
|
|
export function completePaths(name: string, extras: Array<string>): Array<string> {
|
|
|
|
const paths = [];
|
|
|
|
|
|
|
|
const env = process.env[CONFIG_ENV];
|
|
|
|
if (isString(env)) {
|
|
|
|
paths.push(join(env, name));
|
|
|
|
}
|
|
|
|
|
|
|
|
const home = process.env.HOME;
|
|
|
|
if (isString(home)) {
|
|
|
|
paths.push(join(home, name));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isString(__dirname)) {
|
|
|
|
paths.push(join(__dirname, name));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const e of extras) {
|
|
|
|
paths.push(join(e, name));
|
|
|
|
}
|
|
|
|
|
|
|
|
return paths;
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function loadConfig(name: string, ...extras: Array<string>): Promise<any> {
|
2019-06-16 21:15:01 +00:00
|
|
|
const parser = new YamlParser();
|
2019-06-15 20:20:04 +00:00
|
|
|
const paths = completePaths(name, extras);
|
|
|
|
|
|
|
|
for (const p of paths) {
|
|
|
|
const data = await readConfig(p);
|
|
|
|
if (!isNil(data)) {
|
2019-06-16 21:15:01 +00:00
|
|
|
return parser.parse(data);
|
2019-06-15 20:20:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new NotFoundError('unable to load config');
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function readConfig(path: string): Promise<string | undefined> {
|
|
|
|
try {
|
|
|
|
// need to await this read to catch the error, need to catch the error to check the code
|
|
|
|
// tslint:disable-next-line:prefer-immediate-return
|
|
|
|
const data = await readFileSync(path, {
|
|
|
|
encoding: 'utf-8',
|
|
|
|
});
|
|
|
|
return data;
|
|
|
|
} catch (err) {
|
|
|
|
if (err.code === 'ENOENT') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
}
|