Skip to content

Commit 5301335

Browse files
authored
feat!: Lookup configPath in configFiles (#128)
1 parent 466e17b commit 5301335

File tree

6 files changed

+73
-7
lines changed

6 files changed

+73
-7
lines changed

Diff for: README.md

+17-5
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ Default: `null`
165165

166166
An object of configuration files to find. Each property is keyed by the default basename of the file being found, and the value is an array of [path arguments](#path-arguments) of which the order indicates priority to find.
167167

168+
See [Config Files](#config-files) for the config file specification.
169+
168170
**Note:** This option is useful if, for example, you want to support an `.apprc` file in addition to an `appfile.js`. If you only need a single configuration file, you probably don't need this. In addition to letting you find multiple files, this option allows more fine-grained control over how configuration files are located.
169171

170172
Type: `Object`
@@ -337,11 +339,7 @@ const onExecute = function (env, argv) {
337339
};
338340
const onPrepare = function (env) {
339341
const config = env.config['.hacker'];
340-
if (config.hackerfile) {
341-
env.configPath = path.resolve(config.hackerfile);
342-
env.configBase = path.dirname(env.configPath);
343-
}
344-
Hacker.execute(env, onExecute);
342+
Hacker.execute(env, config.forcedFlags, onExecute);
345343
};
346344
Hacker.prepare({}, onPrepare);
347345
```
@@ -457,6 +455,7 @@ A function called after your environment is prepared. A good place to modify the
457455
- `modulePath`: the full path to the local module your project relies on (if found)
458456
- `modulePackage`: the contents of the local module's package.json (if found)
459457
- `configFiles`: an object of filepaths for each found config file (filepath values will be null if not found)
458+
- `config`: an object with keys matching `configFiles` but with the loaded config object
460459

461460
### execute(env, [forcedFlags], callback(env, argv))
462461

@@ -492,6 +491,7 @@ A function called after your application is executed. When invoked, `this` will
492491
- `modulePath`: the full path to the local module your project relies on (if found)
493492
- `modulePackage`: the contents of the local module's package.json (if found)
494493
- `configFiles`: an object of filepaths for each found config file (filepath values will be null if not found)
494+
- `config`: an object with keys matching `configFiles` but with the loaded config object
495495

496496
### events
497497

@@ -582,6 +582,18 @@ Hacker.on('respawn', function (flags, child) {
582582
Event will be triggered for this command:
583583
`hacker --harmony commmand`
584584

585+
## Config files
586+
587+
Liftoff supports a small definition of config files, but all details provided by users will be available in `env.config`.
588+
589+
### `extends`
590+
591+
All `extends` properties will be traversed and become the basis for the resulting config object. Any path provided for `extends` will be loaded with node's `require`, so all extensions and loaders supported on the Liftoff instance will be available to them.
592+
593+
### Field matching the `configName`
594+
595+
Users can override the `configPath` via their config files by specifying a field with the same name as the primary `configName`. For example, the `hackerfile` property in a `configFile` will resolve the `configPath` and `configBase` against the path.
596+
585597
## Examples
586598

587599
Check out how [gulp][gulp-cli-index] uses Liftoff.

Diff for: index.js

+18-2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ Liftoff.prototype.buildEnvironment = function (opts) {
5050

5151
// make a copy of search paths that can be mutated for this run
5252
var searchPaths = this.searchPaths.slice();
53+
// store the instance configName to use in closures without access to `this`
54+
var configName = this.configName;
5355

5456
// calculate current cwd
5557
var cwd = findCwd(opts);
@@ -113,6 +115,13 @@ Liftoff.prototype.buildEnvironment = function (opts) {
113115
'Encountered error when loading config file: ' + configFilePath
114116
);
115117
}
118+
119+
// resolve something like `{ gulpfile: "./abc.xyz" }` to the absolute path
120+
// based on the path of the configFile
121+
if (Object.prototype.hasOwnProperty.call(configFile, configName)) {
122+
configFile[configName] = path.resolve(path.dirname(configFilePath), configFile[configName]);
123+
}
124+
116125
visited[configFilePath] = true;
117126
if (configFile && configFile.extends) {
118127
var nextCwd = path.dirname(configFilePath);
@@ -146,6 +155,13 @@ Liftoff.prototype.buildEnvironment = function (opts) {
146155
return loadConfig(cwd, startingLocation, defaultConfig);
147156
});
148157

158+
var configPathOverride = arrayFind(Object.keys(config), function (key) {
159+
var cfg = config[key];
160+
if (Object.prototype.hasOwnProperty.call(cfg, configName)) {
161+
return cfg[configName];
162+
}
163+
});
164+
149165
// if cwd was provided explicitly, only use it for searching config
150166
if (opts.cwd) {
151167
searchPaths = [cwd];
@@ -156,15 +172,15 @@ Liftoff.prototype.buildEnvironment = function (opts) {
156172

157173
// calculate the regex to use for finding the config file
158174
var configNameSearch = buildConfigName({
159-
configName: this.configName,
175+
configName: configName,
160176
extensions: Object.keys(this.extensions),
161177
});
162178

163179
// calculate configPath
164180
var configPath = findConfig({
165181
configNameSearch: configNameSearch,
166182
searchPaths: searchPaths,
167-
configPath: opts.configPath,
183+
configPath: opts.configPath || configPathOverride,
168184
});
169185

170186
// if we have a config path, save the directory it resides in.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
var path = require('path');
2+
3+
module.exports = {
4+
myappfile: path.join(__dirname, "../override-the-config-path.js"),
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"myappfile": "../override-the-config-path.js"
3+
}

Diff for: test/fixtures/override-the-config-path.js

Whitespace-only changes.

Diff for: test/index.js

+30
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,36 @@ describe('Liftoff', function () {
571571
);
572572
});
573573

574+
it('overrides the configPath if the configName key exists in the config', function (done) {
575+
var app = new Liftoff({
576+
name: 'myapp',
577+
configFiles: {
578+
'override-config-path-absolute': [
579+
{ path: 'test/fixtures/configfiles', extensions: ['.js'] }
580+
],
581+
},
582+
});
583+
app.prepare({}, function (env) {
584+
expect(env.configPath).toMatch(/override-the-config-path\.js$/);
585+
done();
586+
});
587+
});
588+
589+
it('resolves relative configPath if the configName key exists in the config', function (done) {
590+
var app = new Liftoff({
591+
name: 'myapp',
592+
configFiles: {
593+
'override-config-path-relative': [
594+
{ path: 'test/fixtures/configfiles', extensions: ['.json'] }
595+
],
596+
},
597+
});
598+
app.prepare({}, function (env) {
599+
expect(env.configPath).toMatch(/override-the-config-path\.js$/);
600+
done();
601+
});
602+
});
603+
574604
it('should use dirname of configPath if no cwd is specified', function (done) {
575605
var app = new Liftoff({
576606
name: 'myapp',

0 commit comments

Comments
 (0)