question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Let's make awesome validation for the config!

See original GitHub issue

Update/TLDR:

  • This issue was originally about validating brunch-config.js. That’s done (in a general way that ensures that future config is validated too).
  • Then, I suggested better error handling of missing files and valid but bad config. That’s done. (Let’s improve things more as we find them.)
  • What’s left to do is plugin config validation.

The last couple of days I’ve been migrating a legacy project to brunch, and it’s been a very positive experince!

I’ve used brunch a bit a few years ago, so it wasn’t entirely new to me, but I still bumped into a few problems along the way. Most of the time, the problems arose from a mistake I had made in brunch-config.js. Here are a few examples.


I had just finished installing some brunch plugins and making a few edits to brunch-config.js. I then ran brunch b to test it out. (Yes, my primary testing consists of running brunch b and inspecting the output in public/. I don’t bother opening the browser until it looks ok.) This is the result:

$ brunch b
13 Apr 06:06:33 - error: Initialization error - TypeError: stylesheets.map is not a function
  at /home/lydell/myproject/node_modules/deppack/lib/load-globs-styles.js:21:26
  at Array.map (native)
  at Object.keys.map.each.then (/home/lydell/myproject/node_modules/deppack/lib/load-globs-styles.js:15:42)
  at /home/lydell/myproject/node_modules/deppack/lib/deppack.js:71:19

That’s not very helpful! Initially, I had no clue at all what was wrong. I didn’t know if it was my fault, some plugin’s fault or a bug in brunch. I then noticed the word “stylesheets” in the error message, and thought of config.files.stylesheets, but that was a red herring. I then realized that if .map is not a function, that probably means that brunch expects an array in my config, but I gave it something else. I started commenting out my most recent changes in brunch-config.js until the problem went away. Turned out this was the problem:

npm: {
  styles: {
    'font-awesome': 'css/font-awesome.css',
  },
},

… which is supposed to be (note the added [ and ]):

npm: {
  styles: {
    'font-awesome': ['css/font-awesome.css'],
  },
},

Similarly to the above, I Initially thought that npm.static could be used like this:

static: {
  'font-awesome': ['fonts/font-awesome.woff']
},

That gave me this:

$ brunch b
/home/lydell/myproject/node_modules/deppack/lib/deppack.js:34
  const isPackage = path => isNodeModule(path) && (statics || []).indexOf(path) === -1;
                                                                  ^

TypeError: (statics || []).indexOf is not a function
  at Object.path [as isPackage] (/home/lydell/myproject/node_modules/deppack/lib/deppack.js:34:67)
  at Deppack.isNpm (/home/lydell/myproject/node_modules/deppack/lib/deppack.js:100:27)
  at FileList.isIgnored (/home/lydell/myproject/node_modules/brunch/lib/fs_utils/file_list.js:65:17)
  at FileList._change (/home/lydell/myproject/node_modules/brunch/lib/fs_utils/file_list.js:187:26)
  at emitMany (events.js:121:13)
  at FileList.emit (events.js:195:7)
  at BrunchWatcher.changeFileList (/home/lydell/myproject/node_modules/brunch/lib/watch.js:239:19)
  at BrunchWatcher.startCompilation (/home/lydell/myproject/node_modules/brunch/lib/watch.js:314:12)
  at FSWatcher.<anonymous> (/home/lydell/myproject/node_modules/brunch/lib/watch.js:177:14)
  at emitTwo (events.js:100:13)
  at FSWatcher.emit (events.js:185:7)
  at FSWatcher.<anonymous> (/home/lydell/myproject/node_modules/chokidar/index.js:171:15)
  at FSWatcher._emit (/home/lydell/myproject/node_modules/chokidar/index.js:212:5)
  at FSWatcher.NodeFsHandler._handleFile (/home/lydell/myproject/node_modules/chokidar/lib/nodefs-handler.js:275:10)
  at FSWatcher.<anonymous> (/home/lydell/myproject/node_modules/chokidar/lib/nodefs-handler.js:473:21)
  at FSReqWrap.oncomplete (fs.js:82:15)

Once, I thought that the “conventions” option was called “convention”, and was frustrated when my config didn’t make any difference. Then I finally found that pesky missing “s”.


Proposal

eslint and stylelint both validate their config files in an awesome way. They warn about unrecognized (misspelled) options, and make sure that the options are of the correct type.

Here are a few eslint errors:

Definition for rule 'comma-dangel' was not found

Configuration for rule "comma-dangle" is invalid:
Value "always-multilin" must be an enum value.

Configuration for rule "comma-dangle" is invalid:
Severity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed 'true').

stylelint:

Error: Undefined rule "selector-no-ids"

>> Invalid Option: Invalid option value "always-single-lines" for rule "selector-list-comma-space-after"

I think we should follow their lead! It’s definitely worth the extra code!

  • Warn about unrecognized options.
  • Error on invalid option values.

Environment

  1. Brunch: 2.6.5 (both globally and locally)
  2. Node: 5.9.1
  3. NPM: 3.7.3
  4. Operating system: Ubuntu 15.10

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
goshacmdcommented, Apr 25, 2016

@lydell the idea was that plugins shouldn’t depend on skemata directly, instead, Brunch will explicitly pass it. A few upsides I can see is that if there’s some bug in skemata, a new Brunch comes out with bumped skemata version and plugins work as expected.

Leaving the validation entirely to the plugins doesn’t seem very cool from where I stand. The idea is that the all the config schemas (core, plugins’) are merged into one, which ultimately means less false-negatives like (“you have a2, did you mean a1” — when there are both a1 and a2 keys handled by two different plugins) which will happen if there are separate schemas that are not aware of each other.

I understand the current version of skemata might be slightly limiting… which is why we are not exposing it to plugins at the moment. It’ll get better with time and at some point we could allow developers to write their own validators, too, etc.

0reactions
goshacmdcommented, May 10, 2016

@paulmillr I think we can close this now.

Read more comments on GitHub >

github_iconTop Results From Across the Web

thyrlian/AwesomeValidation: Android validation library ...
Implement validation for Android within only 3 steps. Developers should focus on their awesome code, and let the library do the boilerplate.
Read more >
The BEST way to do form validation in JavaScript - YouTube
A lot of JavaScript form validation tutorials won't show you how to write code that can be reused for multiple forms.00:00 Intro01:47 ...
Read more >
ASP.NET Core Configuration - Options Validation
In this article, we're going to learn the importance of options validation and a few ways to implement it in our ASP.NET Core...
Read more >
Validate Spring Boot Configuration Parameters at Startup
Spring Boot has the @ConfigurationProperties annotation to do this binding for the properties defined in application.properties or application.
Read more >
Awesome form validation with Vest and Svelte - codechips
This magic variable is available in every Svelte component and allows you to pass in properties to the container that are not explicitly...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found