-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathutil.js
More file actions
177 lines (154 loc) · 4.74 KB
/
util.js
File metadata and controls
177 lines (154 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/*jslint node: true, nomen: true, regexp: true, stupid: true */
'use strict';
var _ = require('lodash'),
fs = require('fs'),
path = require('path'),
merge = require('merge-recursive').recursive;
var util = {};
/* A valid ENV name to override a config property */
var MATCH_ENV_NAME = /^CONFIG_.*$/;
/**
* Create a browserify plugin that mounts data to a path in the bundle.
* @param {String} mount Path to mount as in Browserify
* @param data Value to serialize into the browserify module
* @return {Function} Browserify middleware
*/
util.browserify = function (mount, data) {
return function (bundle) {
bundle.include(
path.join(mount),
undefined,
'module.exports = ' + JSON.stringify(data) + ';'
);
};
};
/**
* Find existing configs from root path.
* @param {String} root Root path
* @param {Array<String>} configs Files to find
* @return {Array<String>} Absolute files that exist
*/
util.findConfigs = function (path, configs) {
return util.possibleFiles(path, configs).filter(fs.existsSync);
};
/**
* Build config from env & root directory
* @param {String} root Root path
* @param {HashMap<String, String>} env Environment variables
* @param {Object} Config!
*/
util.whereTheMagicHappens = function (root, env) {
/* Load the configs */
var files = [], envs = [];
/* 1. Inheritance */
files = files.concat(util.findConfigs(root, ['config.local.js', 'config.local.json', 'config.js', 'config.json']));
/* 2. Clobbering */
files = files.concat(util.findConfigs(root, ['clobber.js', 'clobber.json']).reverse());
/* 3. Load passed in config */
if (env.CONFIG && fs.existsSync(env.CONFIG)) {
files.push(process.env.CONFIG);
}
/* Require files */
files = files.map(function (file) {
return [file, require(file)];
});
/* 4. Override with the ENV vars */
envs = util.envFilter(env);
/* Compile config */
return {
files: files,
envs: envs,
config: util.merge(files.map(function (config) {
return config[1];
}).concat([util.envObject(env)]))
};
};
/**
* Returns files mapped across every parent directory.
* @param {String} dir Root directory
* @param {Array<String>} files Possible files
* @return {Array<String>} All possible locations for the files
*/
util.possibleFiles = function (dir, files) {
var paths = [];
/* We'll get stuck in an infinite loop if we don't resolve a relative path */
if (dir !== path.resolve('/', dir)) {
throw new Error('Must pass in an absolute path');
}
if (!(files instanceof Array)) {
files = [files];
}
/* Files at the end of the list take higher precedence */
files = files.reverse();
while (true) {
paths = paths.concat(files.map(function (file) {
return path.join(dir, file);
}));
/* Can't go back anymore, we're done! */
if (dir === '/') {
break;
}
dir = path.join(dir, '..');
}
return paths;
};
/**
* Maps an ENV variable to an object.
* @param {String} key ENV's name
* @param {String} value ENV's value
* @return {Object} The ENV variable mapped to an object
*/
util.envToObject = function (key, value) {
var obj = {},
last = obj,
parts = key.substr(7).split('__');
if (value === 'true') {
value = true;
} else if (value === 'false') {
value = false;
} else if (!isNaN(Number(value))) {
value = Number(value);
}
parts.forEach(function (part, index) {
/* Sorry! I couldn't help myself :) */
last = (last[part] = (index < parts.length - 1) ? {} : value);
});
return obj;
};
/**
* Returns the overriding variables from our environment variables.
* @param {Object} env An object representing our environment variables
* @return {Array<Tuple<String, String>>} Filtered ENVs
*/
util.envFilter = function (env) {
return _.map(env, function (value, key) {
return [key, value];
}).filter(function (set) {
return MATCH_ENV_NAME.test(set[0]);
});
};
/**
* Deal with messy calling of the merge function.
*
* @param {Array<Object} objs Array of objects to merge
* @return {Object} Merged objects
*
* @param {Object} obj noop
* @return {Object} noop
*
* @return {Object} noop
*/
util.merge = function (objs) {
return merge.apply(undefined, [{}].concat(objs));
};
/**
* Takes a filtered env list and builds an object!
* @param {Array<Tuple<String, String>>} env Filtered ENVs
* @return {Object} Object built from ENVs
*/
util.envObject = function (env) {
return util.merge(util.envFilter(env).map(function (args) {
return util.envToObject(args[0], args[1]);
}));
};
module.exports = util;