It would be nice if the rules can be a .js file
Example:
yarn depcruise --validate .dependency-cruiser.js packages/*/src
Detect config file extension and load it differently
I'm trying to make general rules for the monorepo, but allow specific packages to extend them differently. For example, our frontend packages have different no-dev-dependency rules than our backend packages (toplevel front-end app packages have no real dependencies once fully built).
The JS file will define a set of common rules, then export 3 variants that extend them via Object.assign - backend apps, frontend apps, shared libraries. Individual packages will have their own .dependency-cruiser.js saying e.g.
module.exports = require('@our/build-tools/dependency-cruiser-rules').frontendApp;
This will also open up a lot of possibilities with regards to the configuration - e.g. "from" and "to" could take function predicates.
Thanks for this (excellent) suggestion @spion.
It should be fairly straightforward to implement - I'll see if I can whip up something in the course of the week (but a PR is welcome as well)
Hi @spion I've published version 4.7.0-beta-0 to npm (with the beta tag), which accepts javascript as config files. Crude documentation is in #74 - but it works as (how I understand what) you requested.
Please give it a spin and let me know if it works for your situation.
Wow, nice! I'll try it out tomorrow and report my findings!
Working perfectly. Thanks, this was just what we needed!
@spion Thanks for testing! I've published it to npm as _latest_ ([email protected]).
Inspired by your setup I've been playing around with reusable/ composable rule sets - and while .js config files increase flexibility to enable it, it required more coding then I liked.
This is why I'm playing with the idea to add an extends attribute to the config, like what eslint and typescript use - and have depcruise handle the extension stuff automatically.
Would this be helpful for your setup?
module.exports = {
extends: './.dependency-cruiser-base', // or something like 'dependency-cruiser/rules/base', or ....
forbidden: [
// rules specific for current repo/ folder + overrides of the 'extends' where necessary
],
options: {
// options specific for current repo/ folder/ ... like webpack configs, tsconfs,
// paths not to follow, ...
}
}
@sverweij personally I didn't feel the need for it,
let forbiddenBase = [...] // base list
let options = {...} // base options
exports.frontendRules = { forbidden: forbiddenBase.concat([...]), options }
exports.backendRules = { forbidden: forbiddenBase.concat([...]), options }
isn't too much IMO.
The main thing for me was that
module.exports = require('@company/build-configs/dependency-cruiser').configType
is very short, and independant of any monorepo structure. If at some point we decide to split things off from the monorepo, yarn install will still provide the private dependency "@company/build-configs"
extends looks nicer definitely, but its not strictly required for us personally (currently there is not a lot of customization for individual packages for dependency-cruiser so presets work well). However, we use a similar scheme for webpack, and there is plenty of individual config customization there. The way we solve it is by writing a function that generates the config :grinning:
exports.makeConfig = function(customization) {
let config = {...}
if (customization.someAspect) { Object.assign(config, stuff); }
...
return config;
}
Then individual webpack.config.js import makeConfig and pass the custom stuff there. (Webpack supports typescript so its really easy to write the config object interface and add extensive inline documentation to any options available. In fact, this makes webpack easier to an extent, since we limit options to what makes sense)
If we use extends, the path will probably be require.resolve('@company/build-configs/dependency-cruiser') to ensure that packages can be separated off the monorepo at any time. On the plus side, if require.resolve is automatically implied for path strings, then the whole thing can work with JSON files too :smile:
@spion thanks for your elaborate (and very clear) response. It confirmed my suspicion and helped me get focus for #79 that shipped with 4.8.0. JSON only will indeed work just as well now (because require.resolve is implied) - but I've started to like the javascript variant too much 馃槃.
B.t.w. your webpack set up is nice - I can see how it helps maintain sanity across many repos.
Most helpful comment
@spion thanks for your elaborate (and very clear) response. It confirmed my suspicion and helped me get focus for #79 that shipped with 4.8.0. JSON only will indeed work just as well now (because
require.resolveis implied) - but I've started to like the javascript variant too much 馃槃.B.t.w. your webpack set up is nice - I can see how it helps maintain sanity across many repos.