1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | import Path from 'path';
|
17 | import shush from 'shush';
|
18 | import debuglog from 'debuglog';
|
19 | import Thing from 'core-util-is';
|
20 | import Config from './config';
|
21 | import Common from './common';
|
22 | import Handlers from './handlers';
|
23 | import Provider from './provider';
|
24 |
|
25 |
|
26 | const debug = debuglog('confit');
|
27 |
|
28 | export default class Factory {
|
29 |
|
30 | constructor({ basedir, protocols = {}, defaults = 'config.json', envignore = []}) {
|
31 | this.envignore = envignore.push('env');
|
32 | this.basedir = basedir;
|
33 | this.protocols = protocols;
|
34 | this.promise = Promise.resolve({})
|
35 | .then(store => Common.merge(Provider.convenience(), store))
|
36 | .then(Factory.conditional(store => {
|
37 | let file = Path.join(this.basedir, defaults);
|
38 | return Handlers.resolveImport(shush(file), this.basedir)
|
39 | .then(data => Common.merge(data, store));
|
40 | }))
|
41 | .then(Factory.conditional(store => {
|
42 | let file = Path.join(this.basedir, `${store.env.env}.json`);
|
43 | return Handlers.resolveImport(shush(file), this.basedir)
|
44 | .then(data => Common.merge(shush(file), store));
|
45 | }))
|
46 | .then(store => Common.merge(Provider.env(envignore), store))
|
47 | .then(store => Common.merge(Provider.argv(), store));
|
48 | }
|
49 |
|
50 | addDefault(obj) {
|
51 | this._add(obj, (store, data) => Common.merge(store, data));
|
52 | return this;
|
53 | }
|
54 |
|
55 | addOverride(obj) {
|
56 | this._add(obj, (store, data) => Common.merge(data, store));
|
57 | return this;
|
58 | }
|
59 |
|
60 | create(cb) {
|
61 | this.promise
|
62 | .then(store => Handlers.resolveImport(store, this.basedir))
|
63 | .then(store => Handlers.resolveCustom(store, this.protocols))
|
64 | .then(store => Handlers.resolveConfig(store))
|
65 | .then(store => cb(null, new Config(store)), cb);
|
66 | }
|
67 |
|
68 | _add(obj, fn) {
|
69 | let data = this._resolveFile(obj);
|
70 | let handler = Handlers.resolveImport(data, this.basedir);
|
71 | this.promise = this.promise.then(store => handler.then(data => fn(store, data)));
|
72 | }
|
73 |
|
74 | _resolveFile(path) {
|
75 | if (Thing.isString(path)) {
|
76 | let file = Common.isAbsolute(path) ? path : Path.join(this.basedir, path);
|
77 | return shush(file);
|
78 | }
|
79 | return path;
|
80 | }
|
81 |
|
82 | static conditional(fn) {
|
83 | return function (store) {
|
84 | try {
|
85 | return fn(store);
|
86 | } catch (err) {
|
87 | if (err.code && err.code === 'MODULE_NOT_FOUND') {
|
88 | debug(`WARNING: ${err.message}`);
|
89 | return store;
|
90 | }
|
91 | throw err;
|
92 | }
|
93 | }
|
94 | }
|
95 |
|
96 | }
|