[
  {
    "path": ".gitignore",
    "content": "## editors\n/.idea\n/.vscode\n*.iml\n\n## system files\n.DS_Store\n\n## dependencies\n/node_modules*\n/npm-debug.log\n\n## testing\n/coverage/\n\n## temp folders\n/.tmp/\n\n# build\n/_site/\n/dist/\n\n# generic logs\n*.log\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\n\nThis project follows _Semantic Versioning_ (aka SemVer). Visit http://semver.org/ to learn more about it.\n\n## Release 3.0.0 (2025-02-13)\n\n- Actually export the plugin\n\n## Release 3.0.0 (2025-02-13)\n\n- Migrate to ESM and flatconfig format\n\n## Release 1.0.0 (2024-01-05)\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 modern-webdev\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# eslint-plugin-barrel-files\n\nBarrel files are files that just re-export a bunch of things from other files. If you're using a bundler, bundlers usually apply treeshaking and dead code elimination algorithms to remove any unused code.\n\nIn many environments however, like test runners, browsers, CDN environments or server side JavaScript runtimes, treeshaking does not get applied. This means that lots of modules get loaded unnecessarily, which can cause significant performance slowdowns.\n\nFor more information, I recommend reading [Speeding up the JavaScript ecosystem - The barrel file debacle](https://marvinh.dev/blog/speeding-up-javascript-ecosystem-part-7/)\n\n## Supported Rules\n\n- [barrel-files/avoid-barrel-files](./docs/rules/avoid-barrel-files.md)\n- [barrel-files/avoid-importing-barrel-files](./docs/rules/avoid-importing-barrel-files.md)\n- [barrel-files/avoid-namespace-import](./docs/rules/avoid-namespace-import.md)\n- [barrel-files/avoid-re-export-all](./docs/rules/avoid-re-export-all.md)\n"
  },
  {
    "path": "docs/rules/avoid-barrel-files.md",
    "content": "# Avoid barrel files\n\n## Rule Details\n\nThis rule disallows _authoring_ barrel files in your project.\n\nExamples of **incorrect** code for this rule:\n\n```js\nexport { foo } from 'foo';\nexport { bar } from 'bar';\nexport { baz } from 'baz';\n```\n\n## Configuration\n\nThis rule takes an optional configuration:\n\n```json\n{\n  \"rules\": {\n    \"barrel-files/avoid-barrel-files\": [\n      2,\n      {\n        \"amountOfExportsToConsiderModuleAsBarrel\": 5\n      }\n    ]\n  }\n}\n```\n"
  },
  {
    "path": "docs/rules/avoid-importing-barrel-files.md",
    "content": "# Avoid importing barrel files\n\n## Rule Details\n\nThis rule aims to avoid importing barrel files that lead to loading large module graphs. This rule is different from the `avoid-barrel-files` rule, which lints against _authoring_ barrel files. This rule lints against _importing_ barrel files.\n\nExamples of **incorrect** code for this rule:\n\n```js\n// If `foo` is a barrel file leading to a module graph of more than 20 modules\nexport { foo } from 'foo';\n```\n\n## Configuration\n\nThis rule takes an optional configuration:\n\n```json\n{\n  \"rules\": {\n    \"barrel-files/avoid-importing-barrel-files\": [\n      2,\n      {\n        \"allowList\": [\"foo\"],\n        \"maxModuleGraphSizeAllowed\": 40,\n        \"amountOfExportsToConsiderModuleAsBarrel\": 5,\n        \"exportConditions\": [\"node\", \"import\"],\n        \"mainFields\": [\"module\", \"main\", \"browser\"],\n        \"extensions\": [\".js\", \".ts\", \".json\", \".node\"],\n        \"tsconfig\": {\n          \"configFile\": \"./tsconfig.json\",\n          \"references\": []\n        }\n      }\n    ]\n  }\n}\n```\n\n### Path Aliases\n\nThe rule can accept an `alias` option whose value can be an object that matches Webpack's [resolve.alias](https://webpack.js.org/configuration/resolve/) configuration.\n\n```js\n// .eslintrc.cjs\nconst path = require('path')\n\nexport default {\n  // ...\n  \"rules\": {\n    \"barrel-files/avoid-importing-barrel-files\": [\n      2,\n      {\n        alias: {\n          // \"@/foo/bar.js\" => \"./src/foo/bar.js\"\n          \"@\": [path.resolve(\".\", \"src\")]\n        }\n      }\n    ]\n  }\n}\n```\n"
  },
  {
    "path": "docs/rules/avoid-namespace-import.md",
    "content": "# Avoid namespace import\n\n## Rule Details\n\nThis rule aims to...\n\nExamples of **incorrect** code for this rule:\n\n```js\nimport * as foo from 'foo';\n```\n\n## Configuration\n\nThis rule takes an optional configuration:\n\n```json\n{\n  \"rules\": {\n    \"barrel-files/avoid-namespace-import\": [\n      2,\n      {\n        \"allowList\": [\"foo\"]\n      }\n    ]\n  }\n}\n```\n"
  },
  {
    "path": "docs/rules/avoid-re-export-all.md",
    "content": "# Avoid re-export all\n\n## Rule Details\n\nThis rule aims to...\n\nExamples of **incorrect** code for this rule:\n\n```js\nexport * from 'foo';\nexport * as foo from 'foo';\n```\n"
  },
  {
    "path": "index.js",
    "content": "import { join, parse } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { dirname } from \"node:path\";\nimport { readFile, readdir } from \"node:fs/promises\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkgJson = JSON.parse(await readFile(join(__dirname, \"./package.json\")));\n\nconst rules = {};\nconst filenames = await readdir(`${__dirname}/lib/rules`);\nfor (const filename of filenames) {\n  const rule = (\n    await import(pathToFileURL(`${__dirname}/lib/rules/${filename}`))\n  ).default;\n\n  const ruleName = parse(filename).name;\n  rules[ruleName] = rule;\n}\n\nconst plugin = {\n  meta: {\n    name: pkgJson.name,\n    version: pkgJson.version,\n  },\n  processors: {},\n  rules,\n  configs: {},\n};\n\n// assign configs here so we can reference `plugin`\nObject.assign(plugin.configs, {\n  recommended: {\n    plugins: {\n      'barrel-files': plugin,\n    },\n    rules: {\n      'barrel-files/avoid-importing-barrel-files': 'error',\n      'barrel-files/avoid-barrel-files': 'error',\n      'barrel-files/avoid-namespace-import': 'error',\n      'barrel-files/avoid-re-export-all': 'error',\n    },\n  },\n});\n\nexport default plugin;"
  },
  {
    "path": "lib/rules/avoid-barrel-files.js",
    "content": "/**\n * @fileoverview avoid-barrel-files\n * @author Pascal Schilp\n */\n//------------------------------------------------------------------------------\n// Rule Definition\n//------------------------------------------------------------------------------\n\nexport default {\n  meta: {\n    type: 'suggestion',\n    docs: {\n      description: \"avoid-barrel-files\",\n      category: 'Performance',\n      recommended: true,\n      url: '../../docs/rules/avoid-barrel-files.md',\n    },\n    schema: [\n      {\n        amountOfExportsToConsiderModuleAsBarrel: {\n          type: 'number',\n          description: 'Minimum amount of exports to consider module as barrelfile',\n          default: 3,\n        },\n      },\n    ],\n  },\n  create: context => ({\n    //----------------------------------------------------------------------\n    // Public\n    //----------------------------------------------------------------------\n    Program(node) {\n      const options = (context.options && context.options[0]) || {};\n      const amountOfExportsToConsiderModuleAsBarrel = options?.amountOfExportsToConsiderModuleAsBarrel ?? 3;\n\n      let declarations = 0;\n      let exports = 0;\n\n      node.body.forEach((n) => {\n        if (n.type === 'VariableDeclaration') {\n          declarations += n.declarations.length;\n        }\n\n        if (\n          n.type === 'FunctionDeclaration' ||\n          n.type === 'ClassDeclaration' ||\n          n.type === 'TSTypeAliasDeclaration' ||\n          n.type === 'TSInterfaceDeclaration'\n        ) {\n          declarations += 1;\n        }\n\n        if (n.type === 'ExportNamedDeclaration') {\n          exports += n.specifiers.length;\n        }\n\n        if (n.type === 'ExportAllDeclaration' && n?.exportKind !== 'type') {\n          exports += 1;\n        }\n\n        if (n.type === 'ExportDefaultDeclaration') {\n          if (\n            n.declaration.type === 'FunctionDeclaration' ||\n            n.declaration.type === 'CallExpression'\n          ) {\n            declarations += 1;\n          } else if (n.declaration.type === 'ObjectExpression') {\n            exports += n.declaration.properties.length;\n          } else {\n            exports += 1;\n          }\n        }\n      });\n\n      if (\n        exports > declarations &&\n        exports > amountOfExportsToConsiderModuleAsBarrel\n      ) {\n        context.report({\n          node,\n          message: \"Avoid barrel files, they slow down performance, and cause large module graphs with modules that go unused.\",\n        });\n      }\n    },\n  }),\n};\n"
  },
  {
    "path": "lib/rules/avoid-importing-barrel-files.js",
    "content": "/**\n * @fileoverview avoid-barrel-files\n * @author Pascal Schilp\n */\n//------------------------------------------------------------------------------\n// Rule Definition\n//------------------------------------------------------------------------------\n\nimport { readFileSync } from 'fs';\nimport path from 'path';\nimport { builtinModules } from 'module';\nimport {\n  count_module_graph_size,\n  is_barrel_file,\n} from 'eslint-barrel-file-utils/index.cjs';\nimport { ResolverFactory } from 'oxc-resolver';\n\n/**\n * @fileoverview Avoid importing barrel files\n * @author Pascal Schilp\n */\n\n//------------------------------------------------------------------------------\n// Rule Definition\n//------------------------------------------------------------------------------\n\nconst cache = {};\n\n// custom error class to emulate oxc_resolver ResolveError enum.\n// `errorVariant` can be equal to a `ResolveError` enum variant.\nclass ResolveError extends Error {\n  constructor(errorVariant = null, message = \"\") {\n    super(message);\n    this.errorVariant = errorVariant;\n    this.message = message;\n  }\n}\n\nexport default {\n  meta: {\n    type: 'problem',\n    fixable: null,\n    docs: {\n      description:\n        'Avoid importing barrel files',\n      recommended: true,\n      url: '../../docs/rules/avoid-importing-barrel-files.md',\n    },\n    schema: [\n      {\n        allowList: {\n          type: 'array',\n          description: 'List of modules from which to allow barrel files',\n          default: [],\n          uniqueItems: true,\n          items: {\n            type: 'string',\n          },\n        },\n      },\n      {\n        maxModuleGraphSizeAllowed: {\n          type: 'number',\n          description: 'Maximum allowed module graph size',\n          default: 20,\n        },\n      },\n      {\n        amountOfExportsToConsiderModuleAsBarrel: {\n          type: 'number',\n          description: 'Amount of exports to consider a module as barrel file',\n          default: 3,\n        },\n      },\n      {\n        debug: {\n          type: 'boolean',\n          description: 'Enabling debug loggin',\n          default: false,\n        },\n      },\n      {\n        exportConditions: {\n          type: 'array',\n          description: 'Export conditions to use to resolve bare module specifiers',\n          default: [],\n          uniqueItems: true,\n          items: {\n            type: 'string',\n          },\n        },\n      },\n      {\n        mainFields: {\n          type: 'array',\n          description: 'Main fields to use to resolve modules',\n          default: [],\n          uniqueItems: true,\n          items: {\n            type: 'string',\n          },\n        },\n      },\n      {\n        extensions: {\n          type: 'array',\n          description: 'Extensions to use to resolve modules',\n          default: [],\n          uniqueItems: true,\n          items: {\n            type: 'string',\n          },\n        },\n      },\n      // schema to match oxc-resolver's TsconfigOptions\n      {\n        tsconfig: {\n          type: 'object',\n          description: 'Options to TsconfigOptions',\n          properties: {\n            configFile: {\n              type: 'string',\n              description: 'Relative path to the configuration file'\n            },\n            references: {\n              type: 'array',\n              description: 'Typescript Project References',\n              items: {\n                type: 'string'\n              }\n            }\n          }\n        }\n      },\n      // NapiResolveOptions.alias\n      {\n        alias: {\n          type: 'object',\n          description: 'Webpack aliases used in imports or requires'\n        }\n      }\n    ],\n  },\n  create(context) {\n    const options = (context.options && context.options[0]) || {};\n    const maxModuleGraphSizeAllowed = options.maxModuleGraphSizeAllowed ?? 20;\n    const debug = options.debug ?? false;\n    const amountOfExportsToConsiderModuleAsBarrel = options.amountOfExportsToConsiderModuleAsBarrel ?? 3;\n    const exportConditions = options.exportConditions ?? [\"node\", \"import\"];\n    const mainFields = options.mainFields ?? [\"module\", \"browser\", \"main\"];\n    const extensions = options.extensions ?? [\".js\", \".ts\", \".tsx\", \".jsx\", \".json\", \".node\"];\n    const tsconfig = options.tsconfig;\n    const alias = options.alias;\n\n    const resolutionOptions = { exportConditions, mainFields, extensions, tsconfig, alias };\n\n    const resolver = new ResolverFactory({\n      tsconfig,\n      alias,\n      conditionNames: exportConditions,\n      mainFields,\n      extensions\n    });\n\n    /**\n     * @param {string} specifier\n     * @returns {boolean}\n     */\n    const isBareModuleSpecifier = specifier => !!specifier?.replace(/'/g, '')[0].match(/[@a-zA-Z]/g);\n\n    /**\n     * @param {number} amount\n     * @returns {string}\n     */\n    const message = (amount, specifier) => `The imported module \"${specifier}\" is a barrel file, which leads to importing a module graph of ${amount} modules, which exceeds the maximum allowed size of ${maxModuleGraphSizeAllowed} modules`\n\n    return {\n      ImportDeclaration(node) {\n        const moduleSpecifier = node.source.value;\n        const currentFileName = context.getFilename();\n\n        if (options?.allowList?.includes(moduleSpecifier)) {\n          return;\n        }\n\n        if (node?.importKind === 'type') {\n          return;\n        }\n\n        if (builtinModules.includes(moduleSpecifier.replace(\"node:\", \"\"))) {\n          return;\n        }\n\n        let resolvedPath;\n        try {\n          resolvedPath = resolver.sync(path.dirname(currentFileName), moduleSpecifier);\n\n          if (resolvedPath.error) {\n            // assuming ResolveError::NotFound if ResolveResult's path value is None\n            if (!resolvedPath.path) {\n              throw new ResolveError(\"NotFound\", resolvedPath.error);\n            }\n\n            throw new ResolveError(null, resolvedPath.error);\n          }\n        } catch (e) {\n          if (!debug) {\n            return\n          }\n\n          if (e instanceof ResolveError) {\n            switch (e.errorVariant) {\n              case \"NotFound\":\n                console.error(`Failed to resolve \"${moduleSpecifier}\" from \"${currentFileName}\": \\n\\n${e.stack}`);\n                break\n              default:\n                console.error(`${e.message}: \\n\\n${e.stack}`);\n            }\n          }\n\n          console.error(`${e}: \\n\\n${e.stack}`);\n          return\n        }\n\n        const fileContent = readFileSync(resolvedPath.path, 'utf8');\n        let isBarrelFile;\n\n        /**\n         * Only cache bare module specifiers, as local files can change\n         */\n        if (isBareModuleSpecifier(moduleSpecifier)) {\n          /**\n           * The module specifier is not cached yet, so we need to analyze and cache it\n           */\n          if (!cache[moduleSpecifier]) {\n            isBarrelFile = is_barrel_file(fileContent, amountOfExportsToConsiderModuleAsBarrel);\n            const moduleGraphSize = isBarrelFile ? count_module_graph_size(resolvedPath.path, resolutionOptions) : -1;\n\n            cache[moduleSpecifier] = {\n              isBarrelFile,\n              moduleGraphSize,\n            };\n\n            if (moduleGraphSize > maxModuleGraphSizeAllowed) {\n              context.report({\n                node: node.source,\n                message: message(moduleGraphSize, moduleSpecifier)\n              });\n            }\n          } else {\n            /**\n             * It is a bare module specifier, but cached, so we can use the cached value\n             */\n\n            if (cache[moduleSpecifier].moduleGraphSize > maxModuleGraphSizeAllowed) {\n              context.report({\n                node: node.source,\n                message: message(cache[moduleSpecifier].moduleGraphSize, moduleSpecifier)\n              });\n            }\n          }\n        } else {\n          /**\n           * Its not a bare module specifier, but local module, so we need to analyze it\n           */\n          const isBarrelFile = is_barrel_file(fileContent, amountOfExportsToConsiderModuleAsBarrel);\n          const moduleGraphSize = isBarrelFile ? count_module_graph_size(resolvedPath.path, resolutionOptions) : -1;\n          if (moduleGraphSize > maxModuleGraphSizeAllowed) {\n            context.report({\n              node: node.source,\n              message: message(moduleGraphSize, moduleSpecifier)\n            });\n          }\n        }\n      },\n    };\n  },\n};\n"
  },
  {
    "path": "lib/rules/avoid-namespace-import.js",
    "content": "/**\n * @fileoverview avoid-namespace-import\n * @author Pascal Schilp\n */\n//------------------------------------------------------------------------------\n// Rule Definition\n//------------------------------------------------------------------------------\n\nexport default {\n  meta: {\n    type: 'suggestion',\n    docs: {\n      description: \"avoid-namespace-import\",\n      category: 'Performance',\n      recommended: true,\n      url: '../../docs/rules/avoid-namespace-import.md',\n    },\n    schema: [\n      {\n        allowList: {\n          type: 'array',\n          description: 'List of namespace imports to allow',\n          default: [],\n          uniqueItems: true,\n          items: {\n            type: 'string',\n          },\n        },\n      },\n    ],\n  },\n  create: context => {\n    const options = (context.options && context.options[0]) || {};\n    const allowList = options.allowList ?? [];\n\n\n    return{\n      //----------------------------------------------------------------------\n      // Public\n      //----------------------------------------------------------------------\n      ImportNamespaceSpecifier(node) {\n        if (node.parent.importKind !== 'type' && !allowList.includes(node.parent.source.value)) {\n          context.report({\n            node,\n            message: \"Avoid namespace imports, it leads to unused imports and prevents treeshaking.\",\n          });\n        }\n      },\n    }\n  },\n};\n"
  },
  {
    "path": "lib/rules/avoid-re-export-all.js",
    "content": "/**\n * @fileoverview avoid-re-export-all\n * @author Pascal Schilp\n */\n//------------------------------------------------------------------------------\n// Rule Definition\n//------------------------------------------------------------------------------\n\nexport default {\n  meta: {\n    type: 'suggestion',\n    docs: {\n      description: \"avoid-re-export-all\",\n      category: 'Performance',\n      recommended: true,\n      url: '../../docs/rules/avoid-re-export-all.md',\n    },\n  },\n  create: context => ({\n    //----------------------------------------------------------------------\n    // Public\n    //----------------------------------------------------------------------\n    ExportAllDeclaration(node) {\n      if (node?.exportKind !== 'type') {\n        context.report({\n          node,\n          message: \"Avoid re-exporting * from a module, it leads to unused imports and prevents treeshaking.\",\n        });\n      }\n    },\n  }),\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"eslint-plugin-barrel-files\",\n  \"version\": \"3.0.1\",\n  \"description\": \"eslint plugin to avoid common errors with barrel files\",\n  \"main\": \"index.js\",\n  \"directories\": {\n    \"doc\": \"docs\",\n    \"lib\": \"lib\",\n    \"test\": \"tests\"\n  },\n  \"type\": \"module\",\n  \"scripts\": {\n    \"test\": \"npm run test:node\",\n    \"test:node\": \"mocha tests --recursive\",\n    \"test:single\": \"mocha tests/lib/rules/avoid-barrel-files-ts.js --watch\"\n  },\n  \"keywords\": [\n    \"eslint\",\n    \"eslintplugin\",\n    \"eslint-plugin\",\n    \"barrel\",\n    \"barrelfiles\"\n  ],\n  \"peerDependencies\": {\n    \"eslint\": \">= 5\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/thepassle/eslint-plugin-barrel-files\"\n  },\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@typescript-eslint/parser\": \"^6.20.0\",\n    \"@typescript-eslint/rule-tester\": \"^7.6.0\",\n    \"mocha\": \"^10.2.0\"\n  },\n  \"bundleDependencies\": [],\n  \"dependencies\": {\n    \"eslint-barrel-file-utils\": \"^0.0.11\",\n    \"oxc-resolver\": \"^1.9.3\"\n  }\n}\n"
  },
  {
    "path": "tests/lib/rules/avoid-barrel-files-ts.js",
    "content": "/**\n * @fileoverview avoid-barrel-files-ts\n * @author Pascal Schilp\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport { RuleTester } from '@typescript-eslint/rule-tester';\nimport { after } from 'node:test';\nimport rule from '../../../lib/rules/avoid-barrel-files.js';\n\nRuleTester.afterAll = after;\n\n//------------------------------------------------------------------------------\n// Tests\n//------------------------------------------------------------------------------\n\nconst ruleTester = new RuleTester({\n  parserOptions: {\n    sourceType: \"module\",\n    ecmaVersion: \"latest\",\n  },\n});\nruleTester.run('avoid-barrel-files ts', rule, {\n  valid: [\n    {\n      code: `\n        type Money = string;\n        export type { Money };\n      `,\n    },\n    {\n      code: `\n        type Money = {\n          amount: string;\n          currency: string;\n        };\n        export type { Money };\n      `,\n    },\n    {\n      code: `\n        interface Money {\n          amount: string;\n          currency: string;\n        };\n        type Country = string;\n        type State = {\n          name: string;\n        };\n        const newSouthWales = {\n          name: \"New South Wales\"\n        };\n        export { newSouthWales }\n        export type { Money, Country, State };\n      `,\n    }\n  ],\n\n  invalid: [\n    {\n      code: `\n        import { Country } from 'geo';\n        type Money = string;\n        type State = {\n          name: string;\n        };\n        interface Person { name: string; age: number; }\n        export type { Money, Country, Person, State };\n      `,\n      errors: [{ message: 'Avoid barrel files, they slow down performance, and cause large module graphs with modules that go unused.' }],\n    }\n  ],\n});\n"
  },
  {
    "path": "tests/lib/rules/avoid-barrel-files.js",
    "content": "/**\n * @fileoverview avoid-barrel-files\n * @author Pascal Schilp\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport { RuleTester } from 'eslint';\nimport rule from '../../../lib/rules/avoid-barrel-files.js';\n\n//------------------------------------------------------------------------------\n// Tests\n//------------------------------------------------------------------------------\n\nconst ruleTester = new RuleTester({\n  parserOptions: {\n    sourceType: \"module\",\n    ecmaVersion: \"latest\",\n  },\n});\nruleTester.run('avoid-barrel-files', rule, {\n  valid: [\n    {\n      code: `\n        let foo;\n        export { foo };\n      `,\n    },\n    {\n      code: `\n        let foo, bar;\n        export { foo, bar };\n      `,\n    },\n    {\n      code: `\n        let foo, bar, baz;\n        export { foo, bar, baz };\n      `,\n    },\n    {\n      code: `\n        let foo, bar, baz, qux;\n        export { foo, bar, baz, qux };\n      `,\n    },\n    {\n      code: `\n        let foo, bar, baz, qux, quux;\n        export { foo, bar, baz, qux };\n      `,\n    },\n    {\n      code: `\n        export default function Foo() {\n          return 'bar';\n        }\n      `,\n      options: [\n        {\n          amountOfExportsToConsiderModuleAsBarrel: 0,\n        },\n      ],\n    },\n    {\n      code: `\n        export default function bar() {}\n      `,\n      options: [\n        {\n          amountOfExportsToConsiderModuleAsBarrel: 0,\n        },\n      ],\n    },\n    {\n      code: `\n        export default defineFoo({});\n      `,\n      options: [\n        {\n          amountOfExportsToConsiderModuleAsBarrel: 0,\n        },\n      ],\n    }\n  ],\n\n  invalid: [\n    {\n      code: `\n        import { bar, baz, qux} from 'foo';\n        let foo;\n        export { foo, bar, baz, qux,  };\n      `,\n      errors: [{ message: 'Avoid barrel files, they slow down performance, and cause large module graphs with modules that go unused.' }],\n    },\n    {\n      code: `\n        export * from 'foo';\n        export * from 'bar';\n        export * from 'baz';\n        export * from 'qux';\n      `,\n      errors: [{ message: 'Avoid barrel files, they slow down performance, and cause large module graphs with modules that go unused.' }],\n    },\n    {\n      code: `export { foo, bar, baz } from 'foo';`,\n      errors: [{ message: 'Avoid barrel files, they slow down performance, and cause large module graphs with modules that go unused.' }],\n      options: [\n        {\n          amountOfExportsToConsiderModuleAsBarrel: 2,\n        },\n      ],\n    },\n    {\n      code: 'export default { var1, var2, var3, var4 };',\n      errors: [{ message: 'Avoid barrel files, they slow down performance, and cause large module graphs with modules that go unused.' }],\n    },\n  ],\n});\n"
  },
  {
    "path": "tests/lib/rules/avoid-namespace-import.js",
    "content": "/**\n * @fileoverview avoid-namespace-import\n * @author Pascal Schilp\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\nimport { RuleTester } from 'eslint';\nimport rule from '../../../lib/rules/avoid-namespace-import.js';\n\n//------------------------------------------------------------------------------\n// Tests\n//------------------------------------------------------------------------------\n\nconst ruleTester = new RuleTester({\n  // parser: require.resolve('@typescript-eslint/parser'),\n  parserOptions: {\n    sourceType: \"module\",\n    ecmaVersion: \"latest\",\n  },\n});\nruleTester.run('avoid-namespace-import', rule, {\n  valid: [\n    'import { foo } from \"foo\";',\n    // 'import type { foo } from \"foo\";',\n    // 'import type * as foo from \"foo\";'\n    {\n      code: 'import * as foo from \"foo\";',\n      options: [\n        {\n          allowList: ['foo'],\n        },\n      ],\n    },\n  ],\n\n  invalid: [\n    {\n      code: 'import * as foo from \"foo\";',\n      errors: [{ message: 'Avoid namespace imports, it leads to unused imports and prevents treeshaking.' }],\n    },\n    {\n      code: 'import * as bar from \"bar\";',\n      errors: [{ message: 'Avoid namespace imports, it leads to unused imports and prevents treeshaking.' }],\n      options: [\n        {\n          allowList: ['foo'],\n        },\n      ],\n    },\n  ],\n});\n"
  },
  {
    "path": "tests/lib/rules/avoid-re-export-all.js",
    "content": "/**\n * @fileoverview avoid-re-export-all\n * @author Pascal Schilp\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\nimport { RuleTester } from 'eslint';\nimport rule from '../../../lib/rules/avoid-re-export-all.js';\n\n\n//------------------------------------------------------------------------------\n// Tests\n//------------------------------------------------------------------------------\n\nconst ruleTester = new RuleTester({\n  // parser: require.resolve('@typescript-eslint/parser'),\n  parserOptions: {\n    sourceType: \"module\",\n    ecmaVersion: \"latest\",\n  },\n});\nruleTester.run('avoid-re-export-all', rule, {\n  valid: [\n    // 'export type { foo } from \"foo\";',\n    // 'export type * as foo from \"foo\";',\n    'export { foo } from \"foo\";',\n    'export { foo as bar } from \"foo\";',\n  ],\n\n  invalid: [\n    {\n      code: 'export * from \"foo\";',\n      errors: [{ message: 'Avoid re-exporting * from a module, it leads to unused imports and prevents treeshaking.' }],\n    },\n    {\n      code: 'export * as foo from \"foo\";',\n      errors: [{ message: 'Avoid re-exporting * from a module, it leads to unused imports and prevents treeshaking.' }],\n    },\n  ],\n});\n"
  }
]