From 403d2a9f2c7566e98d98510c30562ed49a146433 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Wed, 13 Sep 2023 16:49:52 +0300 Subject: [PATCH] feat(vue): fix linting --- .../__snapshots__/application.spec.ts.snap | 57 +++++++++--- .../application/application.spec.ts | 1 + .../__snapshots__/library.spec.ts.snap | 89 +++++++++++++++--- .../src/generators/library/library.spec.ts | 3 +- packages/vue/src/utils/add-linting.ts | 91 ++++++++++++++++++- 5 files changed, 211 insertions(+), 30 deletions(-) diff --git a/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap index f484e817a4731..d91772ccda6e4 100644 --- a/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap +++ b/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap @@ -1,6 +1,45 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`application generator should set up project correctly with given options 1`] = ` +"{ + "root": true, + "ignorePatterns": ["**/*"], + "plugins": ["@nx"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx", "*.vue"], + "rules": { + "@nx/enforce-module-boundaries": [ + "error", + { + "enforceBuildableLibDependency": true, + "allow": [], + "depConstraints": [ + { + "sourceTag": "*", + "onlyDependOnLibsWithTags": ["*"] + } + ] + } + ] + } + }, + { + "files": ["*.ts", "*.tsx"], + "extends": ["plugin:@nx/typescript"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "extends": ["plugin:@nx/javascript"], + "rules": {} + } + ] +} +" +`; + +exports[`application generator should set up project correctly with given options 2`] = ` "import vue from '@vitejs/plugin-vue'; import { defineConfig } from 'vite'; @@ -36,7 +75,7 @@ export default defineConfig({ " `; -exports[`application generator should set up project correctly with given options 2`] = ` +exports[`application generator should set up project correctly with given options 3`] = ` "{ "name": "test", "$schema": "../node_modules/nx/schemas/project-schema.json", @@ -118,7 +157,7 @@ exports[`application generator should set up project correctly with given option " `; -exports[`application generator should set up project correctly with given options 3`] = ` +exports[`application generator should set up project correctly with given options 4`] = ` "{ "extends": [ "plugin:vue/vue3-essential", @@ -130,15 +169,7 @@ exports[`application generator should set up project correctly with given option "ignorePatterns": ["!**/*"], "overrides": [ { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], + "files": ["*.ts", "*.tsx", "*.js", "*.jsx", "*.vue"], "rules": {} } ] @@ -146,7 +177,7 @@ exports[`application generator should set up project correctly with given option " `; -exports[`application generator should set up project correctly with given options 4`] = ` +exports[`application generator should set up project correctly with given options 5`] = ` "import { describe, it, expect } from 'vitest'; import { mount } from '@vue/test-utils'; @@ -161,7 +192,7 @@ describe('App', () => { " `; -exports[`application generator should set up project correctly with given options 5`] = ` +exports[`application generator should set up project correctly with given options 6`] = ` [ ".eslintignore", ".eslintrc.json", diff --git a/packages/vue/src/generators/application/application.spec.ts b/packages/vue/src/generators/application/application.spec.ts index 537d1319ecc3e..00ec828f8e15f 100644 --- a/packages/vue/src/generators/application/application.spec.ts +++ b/packages/vue/src/generators/application/application.spec.ts @@ -20,6 +20,7 @@ describe('application generator', () => { it('should set up project correctly with given options', async () => { await applicationGenerator(tree, { ...options, unitTestRunner: 'vitest' }); + expect(tree.read('.eslintrc.json', 'utf-8')).toMatchSnapshot(); expect(tree.read('test/vite.config.ts', 'utf-8')).toMatchSnapshot(); expect(tree.read('test/project.json', 'utf-8')).toMatchSnapshot(); expect(tree.read('test/.eslintrc.json', 'utf-8')).toMatchSnapshot(); diff --git a/packages/vue/src/generators/library/__snapshots__/library.spec.ts.snap b/packages/vue/src/generators/library/__snapshots__/library.spec.ts.snap index 425e568553b8b..fc1d771dfaa9c 100644 --- a/packages/vue/src/generators/library/__snapshots__/library.spec.ts.snap +++ b/packages/vue/src/generators/library/__snapshots__/library.spec.ts.snap @@ -69,6 +69,78 @@ exports[`lib should add correct jest.config.ts and dependencies to package.json `; exports[`lib should add correct jest.config.ts and dependencies to package.json 2`] = ` +{ + "ignorePatterns": [ + "**/*", + ], + "overrides": [ + { + "files": [ + "*.ts", + "*.tsx", + "*.js", + "*.jsx", + "*.vue", + ], + "rules": { + "@nx/enforce-module-boundaries": [ + "error", + { + "allow": [], + "depConstraints": [ + { + "onlyDependOnLibsWithTags": [ + "*", + ], + "sourceTag": "*", + }, + ], + "enforceBuildableLibDependency": true, + }, + ], + }, + }, + { + "extends": [ + "plugin:@nx/typescript", + ], + "files": [ + "*.ts", + "*.tsx", + ], + "rules": {}, + }, + { + "extends": [ + "plugin:@nx/javascript", + ], + "files": [ + "*.js", + "*.jsx", + ], + "rules": {}, + }, + { + "env": { + "jest": true, + }, + "files": [ + "*.spec.ts", + "*.spec.tsx", + "*.spec.js", + "*.spec.jsx", + ], + "rules": {}, + }, + ], + "plugins": [ + "@nx", + ], + "root": true, +} +`; + +exports[`lib should add correct jest.config.ts and dependencies to package.json 3`] = ` "/* eslint-disable */ export default { displayName: 'my-lib', @@ -91,7 +163,7 @@ export default { " `; -exports[`lib should add correct jest.config.ts and dependencies to package.json 3`] = ` +exports[`lib should add correct jest.config.ts and dependencies to package.json 4`] = ` "{ "presets": ["@nx/js/babel"] } @@ -205,20 +277,7 @@ exports[`lib should generate files 1`] = ` "*.tsx", "*.js", "*.jsx", - ], - "rules": {}, - }, - { - "files": [ - "*.ts", - "*.tsx", - ], - "rules": {}, - }, - { - "files": [ - "*.js", - "*.jsx", + "*.vue", ], "rules": {}, }, diff --git a/packages/vue/src/generators/library/library.spec.ts b/packages/vue/src/generators/library/library.spec.ts index de323718e92d3..2521e2aea5b16 100644 --- a/packages/vue/src/generators/library/library.spec.ts +++ b/packages/vue/src/generators/library/library.spec.ts @@ -87,6 +87,7 @@ describe('lib', () => { it('should add correct jest.config.ts and dependencies to package.json', async () => { await libraryGenerator(tree, { ...defaultSchema, unitTestRunner: 'jest' }); expect(readJson(tree, '/package.json')).toMatchSnapshot(); + expect(readJson(tree, '.eslintrc.json')).toMatchSnapshot(); expect(tree.read('my-lib/jest.config.ts', 'utf-8')).toMatchSnapshot(); expect(tree.read('my-lib/.babelrc', 'utf-8')).toMatchSnapshot(); }); @@ -399,10 +400,10 @@ describe('lib', () => { }); const eslintConfig = readJson(tree, 'my-lib/.eslintrc.json'); - expect(eslintConfig.overrides[0].parserOptions.project).toEqual([ 'my-lib/tsconfig.*?.json', ]); + expect(eslintConfig.overrides[0].files).toContain('*.vue'); }); }); }); diff --git a/packages/vue/src/utils/add-linting.ts b/packages/vue/src/utils/add-linting.ts index 76d4d75711cd6..7d30581e6e034 100644 --- a/packages/vue/src/utils/add-linting.ts +++ b/packages/vue/src/utils/add-linting.ts @@ -1,7 +1,11 @@ import { Tree } from 'nx/src/generators/tree'; import { Linter, lintProjectGenerator } from '@nx/linter'; import { joinPathFragments } from 'nx/src/utils/path'; -import { addDependenciesToPackageJson, runTasksInSerial } from '@nx/devkit'; +import { + addDependenciesToPackageJson, + runTasksInSerial, + updateJson, +} from '@nx/devkit'; import { extraEslintDependencies } from './lint'; import { addExtendsToLintConfig, @@ -44,6 +48,8 @@ export async function addLinting( ]); } + editEslintConfigFiles(host, options.projectRoot, options.rootProject); + let installTask = () => {}; if (!options.skipPackageJson) { installTask = addDependenciesToPackageJson( @@ -58,3 +64,86 @@ export async function addLinting( return () => {}; } } + +function editEslintConfigFiles( + tree: Tree, + projectRoot: string, + rootProject?: boolean +) { + if (tree.exists(joinPathFragments(projectRoot, 'eslint.config.js'))) { + const fileName = joinPathFragments(projectRoot, 'eslint.config.js'); + updateJson(tree, fileName, (json) => { + let updated = false; + for (let override of json.overrides) { + if (override.parserOptions) { + if (!override.files.includes('*.vue')) { + override.files.push('*.vue'); + } + updated = true; + } + } + if (!updated) { + json.overrides = [ + { + files: ['*.ts', '*.tsx', '*.js', '*.jsx', '*.vue'], + rules: {}, + }, + ]; + } + return json; + }); + } else { + const fileName = joinPathFragments(projectRoot, '.eslintrc.json'); + updateJson(tree, fileName, (json) => { + let updated = false; + for (let override of json.overrides) { + if (override.parserOptions) { + if (!override.files.includes('*.vue')) { + override.files.push('*.vue'); + } + updated = true; + } + } + if (!updated) { + json.overrides = [ + { + files: ['*.ts', '*.tsx', '*.js', '*.jsx', '*.vue'], + rules: {}, + }, + ]; + } + return json; + }); + } + + // Edit root config too + if (tree.exists('.eslintrc.base.json')) { + updateJson(tree, '.eslintrc.base.json', (json) => { + for (let override of json.overrides) { + if ( + override.rules && + '@nx/enforce-module-boundaries' in override.rules + ) { + if (!override.files.includes('*.vue')) { + override.files.push('*.vue'); + } + } + } + return json; + }); + } else if (tree.exists('.eslintrc.json') && !rootProject) { + updateJson(tree, '.eslintrc.json', (json) => { + for (let override of json.overrides) { + if ( + override.rules && + '@nx/enforce-module-boundaries' in override.rules + ) { + if (!override.files.includes('*.vue')) { + override.files.push('*.vue'); + } + } + } + return json; + }); + } +}