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' }) {
|
31 | this.basedir = basedir;
|
32 | this.protocols = protocols;
|
33 | this.promise = Promise.resolve({})
|
34 | .then(store => Common.merge(Provider.convenience(), store))
|
35 | .then(Factory.conditional(store => {
|
36 | let file = Path.join(this.basedir, defaults);
|
37 | return Handlers.resolveImport(shush(file), this.basedir)
|
38 | .then(data => Common.merge(data, store));
|
39 | }))
|
40 | .then(Factory.conditional(store => {
|
41 | let file = Path.join(this.basedir, `${store.env.env}.json`);
|
42 | return Handlers.resolveImport(shush(file), this.basedir)
|
43 | .then(data => Common.merge(shush(file), store));
|
44 | }))
|
45 | .then(store => Common.merge(Provider.env(), store))
|
46 | .then(store => Common.merge(Provider.argv(), store));
|
47 | }
|
48 |
|
49 | addDefault(obj) {
|
50 | this._add(obj, (store, data) => Common.merge(store, data));
|
51 | return this;
|
52 | }
|
53 |
|
54 | addOverride(obj) {
|
55 | this._add(obj, (store, data) => Common.merge(data, store));
|
56 | return this;
|
57 | }
|
58 |
|
59 | create(cb) {
|
60 | this.promise
|
61 | .then(store => Handlers.resolveImport(store, this.basedir))
|
62 | .then(store => Handlers.resolveCustom(store, this.protocols))
|
63 | .then(store => Handlers.resolveConfig(store))
|
64 | .then(store => cb(null, new Config(store)), cb);
|
65 | }
|
66 |
|
67 | _add(obj, fn) {
|
68 | let data = this._resolveFile(obj);
|
69 | let handler = Handlers.resolveImport(data, this.basedir);
|
70 | this.promise = this.promise.then(store => handler.then(data => fn(store, data)));
|
71 | }
|
72 |
|
73 | _resolveFile(path) {
|
74 | if (Thing.isString(path)) {
|
75 | let file = Common.isAbsolute(path) ? path : Path.join(this.basedir, path);
|
76 | return shush(file);
|
77 | }
|
78 | return path;
|
79 | }
|
80 |
|
81 | static conditional(fn) {
|
82 | return function (store) {
|
83 | try {
|
84 | return fn(store);
|
85 | } catch (err) {
|
86 | if (err.code && err.code === 'MODULE_NOT_FOUND') {
|
87 | debug(`WARNING: ${err.message}`);
|
88 | return store;
|
89 | }
|
90 | throw err;
|
91 | }
|
92 | }
|
93 | }
|
94 |
|
95 | }
|