Skip to content

Commit

Permalink
feat(core): consolidate ESLint base config filenames and improve file…
Browse files Browse the repository at this point in the history
… detection logic
  • Loading branch information
ndcunningham committed Jan 16, 2025
1 parent 46495eb commit 26e015d
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 126 deletions.
299 changes: 207 additions & 92 deletions packages/eslint/src/generators/lint-project/lint-project.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,119 +42,234 @@ describe('@nx/eslint:lint-project', () => {
});
});

it('should generate a flat eslint config format based on base config (JS with CJS export)', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';

// CJS config
tree.write('eslint.base.config.js', 'module.exports = {};');

await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
describe('Eslint base config named eslint.base.config', () => {
it('should generate a flat eslint config format based on base config (JS with CJS export)', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';

// CJS config
tree.write('eslint.base.config.js', 'module.exports = {};');

await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
});

expect(tree.read('libs/test-lib/eslint.config.cjs', 'utf-8'))
.toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.base.config.js");
module.exports = [
...baseConfig
];
"
`);

process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
});

expect(tree.read('libs/test-lib/eslint.config.cjs', 'utf-8'))
.toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.base.config.js");
it('should generate a flat eslint config format based on base config (JS with MJS export)', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';

// MJS config
tree.write('eslint.base.config.js', 'export default {};');

await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
});

expect(tree.read('libs/test-lib/eslint.config.mjs', 'utf-8'))
.toMatchInlineSnapshot(`
"import baseConfig from "../../eslint.base.config.js";
export default [
...baseConfig
];
"
`);

process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
});

module.exports = [
...baseConfig
];
"
`);
it('should generate a flat eslint config format based on base config (mjs)', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';

// MJS config
tree.write('eslint.base.config.mjs', 'export default {};');

await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
eslintConfigFormat: 'mjs',
});

expect(tree.read('libs/test-lib/eslint.config.mjs', 'utf-8'))
.toMatchInlineSnapshot(`
"import baseConfig from "../../eslint.base.config.mjs";
export default [
...baseConfig
];
"
`);

process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
});

process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
it('should generate a flat eslint config format based on base config CJS', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';

// CJS config
tree.write('eslint.base.config.cjs', 'module.exports = {};');

await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
});

expect(tree.read('libs/test-lib/eslint.config.cjs', 'utf-8'))
.toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.config.cjs");
module.exports = [
...baseConfig
];
"
`);

process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
});
});

it('should generate a flat eslint config format based on base config (JS with MJS export)', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';

// MJS config
tree.write('eslint.base.config.js', 'export default {};');

await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
describe('Eslint base config named eslint.config', () => {
it('should generate a flat eslint config format based on base config (JS with CJS export)', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';

// CJS config
tree.write('eslint.config.js', 'module.exports = {};');

await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
});

expect(tree.read('libs/test-lib/eslint.config.cjs', 'utf-8'))
.toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.config.js");
module.exports = [
...baseConfig
];
"
`);

process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
});

expect(tree.read('libs/test-lib/eslint.config.mjs', 'utf-8'))
.toMatchInlineSnapshot(`
"import baseConfig from "../../eslint.base.config.js";
it('should generate a flat eslint config format based on base config (JS with MJS export)', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';

export default [
...baseConfig
];
"
`);
// MJS config
tree.write('eslint.config.js', 'export default {};');

process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
});
await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
});

it('should generate a flat eslint config format based on base config (mjs)', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';
expect(tree.read('libs/test-lib/eslint.config.mjs', 'utf-8'))
.toMatchInlineSnapshot(`
"import baseConfig from "../../eslint.config.js";
// MJS config
tree.write('eslint.base.config.mjs', 'export default {};');
export default [
...baseConfig
];
"
`);

await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
eslintConfigFormat: 'mjs',
process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
});

expect(tree.read('libs/test-lib/eslint.config.mjs', 'utf-8'))
.toMatchInlineSnapshot(`
"import baseConfig from "../../eslint.base.config.mjs";
export default [
...baseConfig
];
"
`);

process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
});

it('should generate a flat eslint config format based on base config CJS', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';
it('should generate a flat eslint config format based on base config (mjs)', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';

// MJS config
tree.write('eslint.config.mjs', 'export default {};');

await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
eslintConfigFormat: 'mjs',
});

expect(tree.read('libs/test-lib/eslint.config.mjs', 'utf-8'))
.toMatchInlineSnapshot(`
"import baseConfig from "../../eslint.config.mjs";
export default [
...baseConfig
];
"
`);

process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
});

// CJS config
tree.write('eslint.config.cjs', 'module.exports = {};');
it('should generate a flat eslint config format based on base config CJS', async () => {
const originalEslintUseFlatConfigVal = process.env.ESLINT_USE_FLAT_CONFIG;
process.env.ESLINT_USE_FLAT_CONFIG = 'true';

await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
});
// CJS config
tree.write('eslint.config.cjs', 'module.exports = {};');

console.log(tree.children('.'));
await lintProjectGenerator(tree, {
...defaultOptions,
linter: Linter.EsLint,
project: 'test-lib',
setParserOptionsProject: false,
skipFormat: true,
});

expect(tree.read('libs/test-lib/eslint.config.cjs', 'utf-8'))
.toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.config.cjs");
expect(tree.read('libs/test-lib/eslint.config.cjs', 'utf-8'))
.toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.config.cjs");
module.exports = [
...baseConfig
];
"
`);
module.exports = [
...baseConfig
];
"
`);

process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
process.env.ESLINT_USE_FLAT_CONFIG = originalEslintUseFlatConfigVal;
});
});

it('should generate a flat eslint base config ESM', async () => {
Expand Down
10 changes: 2 additions & 8 deletions packages/eslint/src/generators/lint-project/lint-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ import {
generateSpreadElement,
stringifyNodeList,
} from '../utils/flat-config/ast-utils';
import {
baseEsLintConfigFile,
baseEsLintFlatConfigFile,
} from '../../utils/config-file';
import { BASE_ESLINT_CONFIG_FILENAMES } from '../../utils/config-file';
import { hasEslintPlugin } from '../utils/plugin';
import { setupRootEsLint } from './setup-root-eslint';

Expand Down Expand Up @@ -343,10 +340,7 @@ function isBuildableLibraryProject(
*/
function isMigrationToMonorepoNeeded(tree: Tree, graph: ProjectGraph): boolean {
// the base config is already created, migration has been done
if (
tree.exists(baseEsLintConfigFile) ||
tree.exists(baseEsLintFlatConfigFile)
) {
if (BASE_ESLINT_CONFIG_FILENAMES.some((f) => tree.exists(f))) {
return false;
}

Expand Down
9 changes: 4 additions & 5 deletions packages/eslint/src/generators/utils/eslint-file.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { readJson, type Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import * as devkitInternals from 'nx/src/devkit-internals';
import {
BASE_ESLINT_CONFIG_FILENAMES,
ESLINT_CONFIG_FILENAMES,
baseEsLintConfigFile,
} from '../../utils/config-file';
import {
addExtendsToLintConfig,
Expand Down Expand Up @@ -32,12 +32,11 @@ describe('@nx/eslint:lint-file', () => {
}
);

test.each(ESLINT_CONFIG_FILENAMES)(
'should return base file instead %p when calling findEslintFile',
test.each(BASE_ESLINT_CONFIG_FILENAMES)(
'should return base file %p when calling findEslintFile',
(eslintFileName) => {
tree.write(baseEsLintConfigFile, '{}');
tree.write(eslintFileName, '{}');
expect(findEslintFile(tree)).toBe(baseEsLintConfigFile);
expect(findEslintFile(tree)).toBe(eslintFileName);
}
);
});
Expand Down
Loading

0 comments on commit 26e015d

Please sign in to comment.