wbuchwalter / tslint-loader

tslint loader for webpack
193 stars 65 forks source link

ERROR Module build failed: TypeError: ruleConfiguration.forEach is not a function #73

Closed duffbuster closed 7 years ago

duffbuster commented 7 years ago

Getting an error when running Webpack.

ERROR in ./src/index.ts
Module build failed: TypeError: ruleConfiguration.forEach is not a function
    at Object.convertRuleOptions (/Users/colin/Projects/CMS-Web/node_modules/tslint/lib/configuration.js:357:23)
    at Linter.getEnabledRules (/Users/colin/Projects/CMS-Web/node_modules/tslint/lib/linter.js:194:47)
    at Linter.lint (/Users/colin/Projects/CMS-Web/node_modules/tslint/lib/linter.js:76:33)
    at lint (/Users/colin/Projects/CMS-Web/node_modules/tslint-loader/index.js:58:10)
    at Object.module.exports (/Users/colin/Projects/CMS-Web/node_modules/tslint-loader/index.js:128:3)

My Webpack config us just

{
        test: /\.ts$/,
        exclude: /node_modules/,
        loader: 'tslint-loader',
        enforce: 'pre'
},

tslint version: 5.1.0 tslint-loader version: 3.5.2 Webpack version: 2.4.1

mattiLeBlanc commented 7 years ago

+1

having the same issue. I moved the tslint configuration line into the rule:

    {
        enforce: 'pre',
        test: /.ts$/,
        loader: 'tslint-loader',
        exclude: /node_modules/,
        options: {
          configuration:  require( '../tslint.json' )
        }
      },

Still same issue. I dumped the TSLint json and it looks good. There are no errors in my lint configuration.

Webpack version: 2.3.3 tslint-loader version: 3.5.2 tsline: 5.1.0 typescript: 2.2.2

mattiLeBlanc commented 7 years ago

Okay, started to debug and I found the following: The rule configuration going into the convertRuleOptions function in tslint/lib/configuration: line 355 is an object literal, and you are trying to do a forEach on an object literal which is not a native function of Object. So either use the Object.keys() and iterate over the keys or add Lodash forEach to iterate over this object. I am happy to make a pull request?

mattiLeBlanc commented 7 years ago

This fixed in in the TSLINT package, however since that is another package I am not sure how to proceed. Maybe the tslint-loader should offer the rules object in a an array format so that tslint can use the foreach, instead of my suggestion (which might break in other solution if there is an array passed in instead of an object).

When I look at your docs, the configuration expects a rules object so I am not sure how this tslint
would have worked before. Maybe it used to expect an array?

function convertRuleOptions(ruleConfiguration) {

    var output = [];
    var ruleKeys = Object.keys(ruleConfiguration);
    ruleKeys.forEach( function( key ) {
        var partialOptions = ruleConfiguration[ key ];
        var ruleName = key;
        var options = {
            disabledIntervals: [],
            ruleArguments: partialOptions.ruleArguments || [],
            ruleName: ruleName,
            ruleSeverity: partialOptions.ruleSeverity || "error",
        };
        output.push(options);
    });
    // console.log(output);
    // ruleConfiguration.forEach(function (partialOptions, ruleName) {
    //     var options = {
    //         disabledIntervals: [],
    //         ruleArguments: partialOptions.ruleArguments || [],
    //         ruleName: ruleName,
    //         ruleSeverity: partialOptions.ruleSeverity || "error",
    //     };
    //     output.push(options);
    // });
    return output;
}

But I am going to suggest another fix where tslint-loader converts to rules object to an array of rules objects, so that tslint will not through the error of not having a forEach on the prototype.

UPDATE: I came to the conclusion that it is not tslint-loaders issue here, because the function convertRuleOptions in tslint's configuration.js file is doing a foreach on a dictionary. Even if I convert it to array, it's code will fail because ruleName will be a number (the array index). So I will post this issue with TsLint.

sonicoder86 commented 7 years ago

The raw configuration object needs to be transformed in a way that findConfigurationFile works.

mattiLeBlanc commented 7 years ago

Can you show me how? I am just using the tslint-loader, upgraded to a newer version of tslint, tslint-loader and webpack. And since that upgrade I got this issue.

sonicoder86 commented 7 years ago

For Tslint 5 the raw configuration needs to be transformed with parseConfigFile. Fixed in version 3.5.3

mattiLeBlanc commented 7 years ago

I can confirm it solves the problem. Thank you.

DenysVuika commented 7 years ago

The issue is not fixed with 3.5.3 upgrade

Izhaki commented 6 years ago

@blacksonic comment was immensely helpful.

Just in case it helps anyone else, there's an example of working usage of parseConfigFile here.