From 309da6c6fdb752290d19294f3298373d167e62f5 Mon Sep 17 00:00:00 2001 From: davidnhk Date: Wed, 17 Jan 2024 00:09:06 +0000 Subject: [PATCH] GH-1885: eslint config include should have optional folder prefix this close #1885 --- .../src/plugins/rules/link-body-to-issue.js | 2 +- .../plugins/rules/link-body-to-issue.test.js | 11 +- .../plugins/rules/link-title-to-issue.test.js | 3 +- packages/eslint-config/index.mjs | 46 ++--- packages/eslint-config/package.json | 8 +- .../plugins/eslint-plugin-import.mjs | 3 +- .../eslint-config/plugins/eslint-plugin-n.mjs | 3 +- .../plugins/eslint-plugin-prettier.mjs | 3 +- packages/eslint-config/preset/cypress.mjs | 28 +-- packages/eslint-config/preset/javascript.mjs | 57 +++--- packages/eslint-config/preset/jest.mjs | 37 ++-- packages/eslint-config/preset/json.mjs | 24 +-- packages/eslint-config/preset/markdown.mjs | 18 +- packages/eslint-config/preset/nest.mjs | 20 ++- packages/eslint-config/preset/react-jsx.mjs | 50 +++--- packages/eslint-config/preset/storybook.mjs | 22 ++- packages/eslint-config/preset/tailwindcss.mjs | 23 ++- packages/eslint-config/preset/typescript.mjs | 38 ++-- packages/eslint-config/preset/yml.mjs | 10 +- .../eslint-config/utils/file-patterns.mjs | 27 ++- packages/eslint-config/utils/has-config.mjs | 25 +-- .../eslint-config/utils/has-config.test.mjs | 163 +++++++++++------- .../eslint-config/utils/is-default-esm.mjs | 5 +- packages/eslint-config/utils/package-json.mjs | 27 +-- packages/prettier-config/package.json | 2 +- packages/tsconfig/package.json | 2 +- 26 files changed, 375 insertions(+), 282 deletions(-) diff --git a/packages/commitlint-config/src/plugins/rules/link-body-to-issue.js b/packages/commitlint-config/src/plugins/rules/link-body-to-issue.js index 35cc83c9..e5d0cb9b 100644 --- a/packages/commitlint-config/src/plugins/rules/link-body-to-issue.js +++ b/packages/commitlint-config/src/plugins/rules/link-body-to-issue.js @@ -1,5 +1,5 @@ -import { parseIssueFromHeader } from './link-title-to-issue.js'; import { defaultConfig } from './configurations.js'; +import { parseIssueFromHeader } from './link-title-to-issue.js'; const linkBodyToIssue = (parsed, _, value) => { const { issuePrefix = defaultConfig.issuePrefix } = value || {}; diff --git a/packages/commitlint-config/src/plugins/rules/link-body-to-issue.test.js b/packages/commitlint-config/src/plugins/rules/link-body-to-issue.test.js index f530f7e9..2e774427 100644 --- a/packages/commitlint-config/src/plugins/rules/link-body-to-issue.test.js +++ b/packages/commitlint-config/src/plugins/rules/link-body-to-issue.test.js @@ -1,21 +1,22 @@ -import { describe, it } from 'node:test'; import assert from 'node:assert'; +import { describe, it } from 'node:test'; + import linkBodyToIssue from './link-body-to-issue.js'; describe('rule: link-body-to-issue', () => { function createParsed({ body, footer, header }) { return { - header, body, footer, + header, }; } it('return true when body have linking keyword and issue is match to header', () => { const [rulePass, failureReason] = linkBodyToIssue( createParsed({ - header: 'GH-1234: what is that', body: 'this close #1234', + header: 'GH-1234: what is that', }), null, ); @@ -25,8 +26,8 @@ describe('rule: link-body-to-issue', () => { it('return false when body have linking keyword but mismatch issue id to header', () => { const [rulePass, failureReason] = linkBodyToIssue( createParsed({ - header: 'GH-4321: what is that', body: 'this close #1234', + header: 'GH-4321: what is that', }), null, ); @@ -40,7 +41,7 @@ describe('rule: link-body-to-issue', () => { it("return true when body don't have linking keyword but have commit message", () => { ['#1234', 'GH-1234'].forEach(body => { const [rulePass, failureReason] = linkBodyToIssue( - createParsed({ header: 'GH-1234: what is that', body: body }), + createParsed({ body: body, header: 'GH-1234: what is that' }), null, ); assert.strictEqual(rulePass, true, failureReason); diff --git a/packages/commitlint-config/src/plugins/rules/link-title-to-issue.test.js b/packages/commitlint-config/src/plugins/rules/link-title-to-issue.test.js index 9aaf9c60..90938e7f 100644 --- a/packages/commitlint-config/src/plugins/rules/link-title-to-issue.test.js +++ b/packages/commitlint-config/src/plugins/rules/link-title-to-issue.test.js @@ -1,5 +1,6 @@ -import { describe, it } from 'node:test'; import assert from 'node:assert'; +import { describe, it } from 'node:test'; + import linkTitleToIssue from './link-title-to-issue.js'; describe('rule: link-title-to-issue', () => { diff --git a/packages/eslint-config/index.mjs b/packages/eslint-config/index.mjs index 00eb4ac9..41b9575b 100644 --- a/packages/eslint-config/index.mjs +++ b/packages/eslint-config/index.mjs @@ -1,17 +1,18 @@ -import jsCommonConfig from './preset/javascript.mjs'; +import eslintGlobals from 'globals'; + import cypressConfig from './preset/cypress.mjs'; -import jestConfig from "./preset/jest.mjs" +import jsCommonConfig from './preset/javascript.mjs'; +import jestConfig from './preset/jest.mjs'; import jsonConfig from './preset/json.mjs'; +import markdownConfig from './preset/markdown.mjs'; +import nestConfig from './preset/nest.mjs'; +import reactConfig from './preset/react-jsx.mjs'; +import storybookConfig from './preset/storybook.mjs'; +import tailwindCSSConfig from './preset/tailwindcss.mjs'; +import typescriptConfig from './preset/typescript.mjs'; +import ymlConfig from './preset/yml.mjs'; import { hasConfig } from './utils/has-config.mjs'; -import eslintGlobals from "globals"; -import markdownConfig from "./preset/markdown.mjs" -import nestConfig from "./preset/nest.mjs" -import reactConfig from "./preset/react-jsx.mjs" -import storybookConfig from "./preset/storybook.mjs" -import typescriptConfig from "./preset/typescript.mjs" -import tailwindCSSConfig from "./preset/tailwindcss.mjs" -import ymlConfig from "./preset/yml.mjs" -import {isDefaultEsm} from "./utils/is-default-esm.mjs" +import { isDefaultEsm } from './utils/is-default-esm.mjs'; const hasReact = await hasConfig([ { dependency: 'react', type: 'dependency' }, @@ -47,7 +48,7 @@ const hasTailwindcss = await hasConfig([ { dependency: 'tailwindcss', dependencyType: 'dev', type: 'dependency' }, ]); -const isDefaultESModule = await isDefaultEsm() +const isDefaultESModule = await isDefaultEsm(); const eslintConfig = [ jsCommonConfig, @@ -56,17 +57,18 @@ const eslintConfig = [ ymlConfig, hasTypescript ? typescriptConfig : [], hasReact ? reactConfig : [], - hasJest ? jestConfig: [], + hasJest ? jestConfig : [], hasCypress ? cypressConfig : [], - hasNest ? nestConfig: [], - hasStorybook ? storybookConfig: [], - hasTailwindcss ? tailwindCSSConfig: [], + hasNest ? nestConfig : [], + hasStorybook ? storybookConfig : [], + hasTailwindcss ? tailwindCSSConfig : [], ].flat(); -export default eslintConfig +export default eslintConfig; export function withConfigurationPrint() { - return (config) => { + return config => { + // eslint-disable-next-line no-console console.log(` hasTypescript: ${hasTypescript} hasReact: ${hasReact} @@ -76,9 +78,9 @@ hasNest: ${hasNest} hasStorybook: ${hasStorybook} hasTailwindcss: ${hasTailwindcss} isDefaultEsm: ${isDefaultESModule} -`) - return config - } +`); + return config; + }; } -export const globals = eslintGlobals \ No newline at end of file +export const globals = eslintGlobals; diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 44643884..3c3ffb1a 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -36,19 +36,19 @@ "eslint": "8.56.0" }, "engines": { - "node": ">=14", + "node": ">=18", "yarn": "Use npm" }, "exports": { ".": { "import": "./index.mjs" }, - "./plugins/eslint-plugin-n": { - "import": "./plugins/eslint-plugin-n.mjs" - }, "./plugins/eslint-plugin-import": { "import": "./plugins/eslint-plugin-import.mjs" }, + "./plugins/eslint-plugin-n": { + "import": "./plugins/eslint-plugin-n.mjs" + }, "./plugins/eslint-plugin-prettier": { "import": "./plugins/eslint-plugin-prettier.mjs" } diff --git a/packages/eslint-config/plugins/eslint-plugin-import.mjs b/packages/eslint-config/plugins/eslint-plugin-import.mjs index 49d829de..ed0bcafa 100644 --- a/packages/eslint-config/plugins/eslint-plugin-import.mjs +++ b/packages/eslint-config/plugins/eslint-plugin-import.mjs @@ -1,4 +1,3 @@ import eslintPluginImport from 'eslint-plugin-import'; - -export default eslintPluginImport; \ No newline at end of file +export default eslintPluginImport; diff --git a/packages/eslint-config/plugins/eslint-plugin-n.mjs b/packages/eslint-config/plugins/eslint-plugin-n.mjs index f93f3a07..600bfcba 100644 --- a/packages/eslint-config/plugins/eslint-plugin-n.mjs +++ b/packages/eslint-config/plugins/eslint-plugin-n.mjs @@ -1,4 +1,3 @@ import eslintPluginN from 'eslint-plugin-n'; - -export default eslintPluginN; \ No newline at end of file +export default eslintPluginN; diff --git a/packages/eslint-config/plugins/eslint-plugin-prettier.mjs b/packages/eslint-config/plugins/eslint-plugin-prettier.mjs index f6b0078e..994cc89a 100644 --- a/packages/eslint-config/plugins/eslint-plugin-prettier.mjs +++ b/packages/eslint-config/plugins/eslint-plugin-prettier.mjs @@ -1,2 +1,3 @@ import eslintPluginPrettier from 'eslint-plugin-prettier'; -export default eslintPluginPrettier; \ No newline at end of file + +export default eslintPluginPrettier; diff --git a/packages/eslint-config/preset/cypress.mjs b/packages/eslint-config/preset/cypress.mjs index 62bd0b94..fcb143d5 100644 --- a/packages/eslint-config/preset/cypress.mjs +++ b/packages/eslint-config/preset/cypress.mjs @@ -1,24 +1,30 @@ -import eslintPluginCypress from "eslint-plugin-cypress" -import {typescriptFileSuffixes, jsFileSuffixes} from "../utils/file-patterns.mjs" +import eslintPluginCypress from 'eslint-plugin-cypress'; + +import { + jsFileSuffixes, + typescriptFileSuffixes, +} from '../utils/file-patterns.mjs'; export default [ { - plugins: { - cypress: eslintPluginCypress, - }, files: [ - [...jsFileSuffixes, ...typescriptFileSuffixes].map((fileSuffix) => `*.cy.${fileSuffix}`), - 'cypress/**/*', + [...jsFileSuffixes, ...typescriptFileSuffixes].map( + fileSuffix => `**/*.cy.${fileSuffix}`, + ), + 'cypress/**/*', ].flat(), languageOptions: { globals: { - ...eslintPluginCypress.environments.globals - } + ...eslintPluginCypress.environments.globals, + }, + }, + plugins: { + cypress: eslintPluginCypress, }, rules: { ...eslintPluginCypress.configs.recommended.rules, 'cypress/no-pause': 'error', 'no-unused-expressions': 'off', }, - } -] + }, +]; diff --git a/packages/eslint-config/preset/javascript.mjs b/packages/eslint-config/preset/javascript.mjs index 4f4c00f1..9ad13ab0 100644 --- a/packages/eslint-config/preset/javascript.mjs +++ b/packages/eslint-config/preset/javascript.mjs @@ -1,54 +1,49 @@ +import js from '@eslint/js'; import eslintPluginImport from 'eslint-plugin-import'; import eslintPluginN from 'eslint-plugin-n'; import eslintPluginPrettier from 'eslint-plugin-prettier'; import eslintPluginSimpleImportSort from 'eslint-plugin-simple-import-sort'; import eslintPluginSortDestructureKeys from 'eslint-plugin-sort-destructure-keys'; import eslintPluginSortKeysFix from 'eslint-plugin-sort-keys-fix'; -import eslintPluginUnicorn from "eslint-plugin-unicorn" -import js from "@eslint/js"; -import {isDefaultEsm} from "../utils/is-default-esm.mjs"; -import {jsFileSuffixes, typescriptFileSuffixes} from "../utils/file-patterns.mjs" -import globals from "globals"; +import eslintPluginUnicorn from 'eslint-plugin-unicorn'; +import globals from 'globals'; -const isDefaultESModule = await isDefaultEsm() -const esmSuffixes = ['*.jsx', - '*.mjs', - '*.ts', - '*.tsx', - '*.mts', - '*.mtsx',]; +import { + jsFileSuffixes, + typescriptFileSuffixes, +} from '../utils/file-patterns.mjs'; +import { isDefaultEsm } from '../utils/is-default-esm.mjs'; + +const isDefaultESModule = await isDefaultEsm(); +const esmSuffixes = ['*.jsx', '*.mjs', '*.ts', '*.tsx', '*.mts', '*.mtsx']; export default [ { - files: ['*.js'], + files: ['**/*.js'], languageOptions: { ecmaVersion: 'latest', - sourceType: isDefaultESModule ? 'commonjs': 'module', - } + sourceType: isDefaultESModule ? 'commonjs' : 'module', + }, }, { - files: esmSuffixes, + files: esmSuffixes.map(fileSuffix => `**/${fileSuffix}`), languageOptions: { ecmaVersion: 'latest', sourceType: 'module', }, }, { - files: [ - '*.cjs', - '*.cts', - '*.ctsx', - '*.cjsx' - ], + files: ['*.cjs', '*.cts', '*.ctsx', '*.cjsx'].map( + fileSuffix => `**/${fileSuffix}`, + ), languageOptions: { ecmaVersion: 'latest', sourceType: 'commonjs', }, }, { - files: [ - ...jsFileSuffixes, - ...typescriptFileSuffixes, - ], + files: [...jsFileSuffixes, ...typescriptFileSuffixes].map( + fileSuffix => `**/*.${fileSuffix}`, + ), plugins: { import: eslintPluginImport, n: eslintPluginN, @@ -59,7 +54,7 @@ export default [ }, rules: { ...js.configs.recommended.rules, // Recommended config applied to all files - ...eslintPluginImport.configs.recommended.rules, + // ...eslintPluginImport.configs.recommended.rules, ...eslintPluginN.configs['recommended-module'].rules, 'block-scoped-var': 'error', 'import/first': 'error', @@ -116,13 +111,15 @@ export default [ }, }, { - files: isDefaultESModule ? ['*.js',...esmSuffixes] : esmSuffixes, + files: (isDefaultESModule ? ['*.js', ...esmSuffixes] : esmSuffixes).map( + fileSuffix => `**/${fileSuffix}`, + ), languageOptions: { ecmaVersion: 'latest', - sourceType: 'module', globals: { ...globals.es2024, }, + sourceType: 'module', }, plugins: { import: eslintPluginImport, @@ -131,7 +128,7 @@ export default [ rules: { 'import/extensions': ['error', 'ignorePackages'], 'n/no-missing-import': ['off'], - 'unicorn/consistent-function-scoping': 'error', + 'unicorn/consistent-function-scoping': 'off', 'unicorn/prefer-node-protocol': 'error', }, }, diff --git a/packages/eslint-config/preset/jest.mjs b/packages/eslint-config/preset/jest.mjs index 19df0f53..22089e7f 100644 --- a/packages/eslint-config/preset/jest.mjs +++ b/packages/eslint-config/preset/jest.mjs @@ -1,20 +1,25 @@ -import eslintPluginJest from "eslint-plugin-jest" -import eslintParserTypescript from "@typescript-eslint/parser" -import eslintPluginTypescript from "@typescript-eslint/eslint-plugin" +import eslintPluginTypescript from '@typescript-eslint/eslint-plugin'; +import eslintParserTypescript from '@typescript-eslint/parser'; +import eslintPluginJest from 'eslint-plugin-jest'; -import {typescriptTestFilePatterns, jsTestFilePatterns} from "../utils/file-patterns.mjs" +import { + jsTestFilePatterns, + typescriptTestFilePatterns, +} from '../utils/file-patterns.mjs'; export default [ { - files: [...jsTestFilePatterns,...typescriptTestFilePatterns], + files: [...jsTestFilePatterns, ...typescriptTestFilePatterns].map( + fileSuffix => `**/${fileSuffix}`, + ), + languageOptions: { + globals: { + ...eslintPluginJest.configs.recommended.env, + }, + }, plugins: { jest: eslintPluginJest, }, - languageOptions: { - globals: { - ...eslintPluginJest.configs.recommended.env - } - }, rules: { ...eslintPluginJest.configs.recommended.rules, 'jest/consistent-test-it': [ @@ -35,13 +40,13 @@ export default [ }, }, { - plugins: { - '@typescript-eslint': eslintPluginTypescript, - }, + files: typescriptTestFilePatterns.map(fileSuffix => `**/${fileSuffix}`), languageOptions: { parser: eslintParserTypescript, }, - files: typescriptTestFilePatterns, + plugins: { + '@typescript-eslint': eslintPluginTypescript, + }, rules: { '@typescript-eslint/ban-ts-comment': [ 'error', @@ -53,5 +58,5 @@ export default [ }, ], }, - } -] \ No newline at end of file + }, +]; diff --git a/packages/eslint-config/preset/json.mjs b/packages/eslint-config/preset/json.mjs index 4d46c8d8..ccf48552 100644 --- a/packages/eslint-config/preset/json.mjs +++ b/packages/eslint-config/preset/json.mjs @@ -1,17 +1,17 @@ -import eslintPluginJson from "eslint-plugin-jsonc" -import eslintParserJson from "jsonc-eslint-parser" -import eslintPluginJsonSchemaValidator from "eslint-plugin-json-schema-validator" -import eslintPluginNodeDependencies from "eslint-plugin-node-dependencies" +import eslintPluginJsonSchemaValidator from 'eslint-plugin-json-schema-validator'; +import eslintPluginJson from 'eslint-plugin-jsonc'; +import eslintPluginNodeDependencies from 'eslint-plugin-node-dependencies'; +import eslintParserJson from 'jsonc-eslint-parser'; export default [ { - files: ['*.json'], - plugins: { - jsonc: eslintPluginJson, - }, + files: ['**/*.json'], + ignores: ['package-lock.json'], languageOptions: { parser: eslintParserJson, - + }, + plugins: { + jsonc: eslintPluginJson, }, rules: { ...eslintPluginJson.configs.prettier.rules, @@ -19,7 +19,7 @@ export default [ }, }, { - files: ['package.json'], + files: ['**/package.json'], plugins: { 'json-schema-validator': eslintPluginJsonSchemaValidator, 'node-dependencies': eslintPluginNodeDependencies, @@ -93,5 +93,5 @@ export default [ 'node-dependencies/compat-engines': 'off', 'node-dependencies/valid-semver': 'off', }, - } -] \ No newline at end of file + }, +]; diff --git a/packages/eslint-config/preset/markdown.mjs b/packages/eslint-config/preset/markdown.mjs index c12e72bd..78494a79 100644 --- a/packages/eslint-config/preset/markdown.mjs +++ b/packages/eslint-config/preset/markdown.mjs @@ -1,15 +1,15 @@ -import eslintPluginMarkdownlint from "eslint-plugin-markdownlint"; -import eslintPluginMarkdownlintParser from "eslint-plugin-markdownlint/parser.js"; +import eslintPluginMarkdownlint from 'eslint-plugin-markdownlint'; +import eslintPluginMarkdownlintParser from 'eslint-plugin-markdownlint/parser.js'; export default [ { - files: ['*.md'], - plugins: {markdownlint: eslintPluginMarkdownlint}, + files: ['**/*.md'], languageOptions: { - parser: eslintPluginMarkdownlintParser + parser: eslintPluginMarkdownlintParser, }, + plugins: { markdownlint: eslintPluginMarkdownlint }, rules: { - ...eslintPluginMarkdownlint.configs.recommended.rules - } - } -] \ No newline at end of file + ...eslintPluginMarkdownlint.configs.recommended.rules, + }, + }, +]; diff --git a/packages/eslint-config/preset/nest.mjs b/packages/eslint-config/preset/nest.mjs index 19527275..e36b9057 100644 --- a/packages/eslint-config/preset/nest.mjs +++ b/packages/eslint-config/preset/nest.mjs @@ -1,10 +1,12 @@ -import {typescriptFileSuffixes} from "../utils/file-patterns.mjs"; +import { typescriptFileSuffixes } from '../utils/file-patterns.mjs'; -export default [{ - files: [typescriptFileSuffixes], - rules: { - 'dot-notation': 'off', - 'max-params': 'off', - 'no-useless-constructor': 'off', - }, -}]; +export default [ + { + files: typescriptFileSuffixes.map(ext => `**/*.${ext}`), + rules: { + 'dot-notation': 'off', + 'max-params': 'off', + 'no-useless-constructor': 'off', + }, + }, +]; diff --git a/packages/eslint-config/preset/react-jsx.mjs b/packages/eslint-config/preset/react-jsx.mjs index ac53d4ca..ec13c003 100644 --- a/packages/eslint-config/preset/react-jsx.mjs +++ b/packages/eslint-config/preset/react-jsx.mjs @@ -1,19 +1,21 @@ -import {typescriptJSXFileSuffixes, jsJSXFileSuffixes, jsJSXTestFilePatterns, typescriptJSXTestFilePattern} from "../utils/file-patterns.mjs" -import eslintPluginReact from "eslint-plugin-react" -import eslintPluginReactHooks from "eslint-plugin-react-hooks" -import eslintPluginReactRefresh from "eslint-plugin-react-refresh" -import eslintPluginTestingLibrary from "eslint-plugin-testing-library" import eslintPluginImport from 'eslint-plugin-import'; +import eslintPluginReact from 'eslint-plugin-react'; +import eslintPluginReactHooks from 'eslint-plugin-react-hooks'; +import eslintPluginReactRefresh from 'eslint-plugin-react-refresh'; +import eslintPluginTestingLibrary from 'eslint-plugin-testing-library'; + +import { + jsJSXFileSuffixes, + jsJSXTestFilePatterns, + typescriptJSXFileSuffixes, + typescriptJSXTestFilePattern, +} from '../utils/file-patterns.mjs'; export default [ { - files: [...jsJSXFileSuffixes, ...typescriptJSXFileSuffixes].map((ext) => `*.${ext}`), - plugins: { - react: eslintPluginReact, - 'react-hooks': eslintPluginReactHooks, - 'react-refresh': eslintPluginReactRefresh, - 'import': eslintPluginImport, - }, + files: [...jsJSXFileSuffixes, ...typescriptJSXFileSuffixes].map( + ext => `**/*.${ext}`, + ), languageOptions: { parserOptions: { ecmaFeatures: { @@ -21,10 +23,11 @@ export default [ }, }, }, - settings: { - react: { - version: 'detect', - }, + plugins: { + import: eslintPluginImport, + react: eslintPluginReact, + 'react-hooks': eslintPluginReactHooks, + 'react-refresh': eslintPluginReactRefresh, }, rules: { ...eslintPluginReact.configs.recommended.rules, @@ -36,15 +39,22 @@ export default [ 'react/jsx-sort-props': 'error', 'react/react-in-jsx-scope': 'off', }, + settings: { + react: { + version: 'detect', + }, + }, }, { - files: typescriptJSXFileSuffixes.map((ext) => `*.${ext}`), + files: typescriptJSXFileSuffixes.map(ext => `**/*.${ext}`), rules: { 'react/prop-types': 'off', }, }, { - files: [...typescriptJSXTestFilePattern, ...jsJSXTestFilePatterns], + files: [...typescriptJSXTestFilePattern, ...jsJSXTestFilePatterns].map( + ext => `**/*.${ext}`, + ), plugins: { 'testing-library': eslintPluginTestingLibrary, }, @@ -54,5 +64,5 @@ export default [ 'react/prop-types': 'off', 'testing-library/prefer-screen-queries': 'error', }, - } -] \ No newline at end of file + }, +]; diff --git a/packages/eslint-config/preset/storybook.mjs b/packages/eslint-config/preset/storybook.mjs index 73ead72e..abc2eefd 100644 --- a/packages/eslint-config/preset/storybook.mjs +++ b/packages/eslint-config/preset/storybook.mjs @@ -1,15 +1,21 @@ -import eslintPluginStorybook from "eslint-plugin-storybook" -import {jsJSXFileSuffixes, typescriptJSXFileSuffixes} from "../utils/file-patterns.mjs" import eslintPluginImport from 'eslint-plugin-import'; -import eslintPluginReactHooks from "eslint-plugin-react-hooks" +import eslintPluginReactHooks from 'eslint-plugin-react-hooks'; +import eslintPluginStorybook from 'eslint-plugin-storybook'; + +import { + jsJSXFileSuffixes, + typescriptJSXFileSuffixes, +} from '../utils/file-patterns.mjs'; export default [ { - files: [...jsJSXFileSuffixes, ...typescriptJSXFileSuffixes].map((ext) => `*.stories.${ext}`), + files: [...jsJSXFileSuffixes, ...typescriptJSXFileSuffixes].map( + ext => `**/*.stories.${ext}`, + ), plugins: { + import: eslintPluginImport, + 'react-hooks': eslintPluginReactHooks, storybook: eslintPluginStorybook, - 'import': eslintPluginImport, - 'react-hooks': eslintPluginReactHooks, }, rules: { ...eslintPluginStorybook.configs.recommended.rules, @@ -17,5 +23,5 @@ export default [ 'import/no-named-export': 'off', 'react-hooks/rules-of-hooks': 'off', }, - } -] + }, +]; diff --git a/packages/eslint-config/preset/tailwindcss.mjs b/packages/eslint-config/preset/tailwindcss.mjs index a376a014..37b47f04 100644 --- a/packages/eslint-config/preset/tailwindcss.mjs +++ b/packages/eslint-config/preset/tailwindcss.mjs @@ -1,15 +1,22 @@ -import eslintPluginTailwindCSS from "eslint-plugin-tailwindcss" -import {jsJSXFileSuffixes, typescriptJSXFileSuffixes} from "../utils/file-patterns.mjs" +import eslintPluginTailwindCSS from 'eslint-plugin-tailwindcss'; + +import { + jsJSXFileSuffixes, + typescriptJSXFileSuffixes, +} from '../utils/file-patterns.mjs'; + export default [ { - files: [...jsJSXFileSuffixes, ...typescriptJSXFileSuffixes].map(ext => `*.${ext}`), + files: [...jsJSXFileSuffixes, ...typescriptJSXFileSuffixes].map( + ext => `**/*.${ext}`, + ), plugins: { - tailwindcss: eslintPluginTailwindCSS, + tailwindcss: eslintPluginTailwindCSS, }, rules: { ...eslintPluginTailwindCSS.configs.recommended.rules, - 'tailwindcss/classnames-order': 'error', - 'tailwindcss/no-custom-classname': 'error', + 'tailwindcss/classnames-order': 'error', + 'tailwindcss/no-custom-classname': 'error', }, - } -] \ No newline at end of file + }, +]; diff --git a/packages/eslint-config/preset/typescript.mjs b/packages/eslint-config/preset/typescript.mjs index 6809ff18..6e5aa21e 100644 --- a/packages/eslint-config/preset/typescript.mjs +++ b/packages/eslint-config/preset/typescript.mjs @@ -1,24 +1,20 @@ -import eslintPluginImportTypescript from "eslint-plugin-import" -import eslintPluginTypescriptSortKeys from "eslint-plugin-typescript-sort-keys" -import eslintPluginTypescript from "@typescript-eslint/eslint-plugin" -import eslintParserTypescript from "@typescript-eslint/parser" -import {typescriptFileSuffixes} from "../utils/file-patterns.mjs" +import eslintPluginTypescript from '@typescript-eslint/eslint-plugin'; +import eslintParserTypescript from '@typescript-eslint/parser'; +import eslintPluginImportTypescript from 'eslint-plugin-import'; +import eslintPluginTypescriptSortKeys from 'eslint-plugin-typescript-sort-keys'; + +import { typescriptFileSuffixes } from '../utils/file-patterns.mjs'; + export default [ { - files: typescriptFileSuffixes.map(ext => `*.${ext}`), + files: typescriptFileSuffixes.map(ext => `**/*.${ext}`), languageOptions: { - parser: eslintParserTypescript, + parser: eslintParserTypescript, }, plugins: { - '@typescript-eslint': eslintPluginTypescript, - 'import': eslintPluginImportTypescript, - 'typescript-sort-keys': eslintPluginTypescriptSortKeys, - }, - settings: { - ...eslintPluginImportTypescript.configs.typescript.settings, - 'import/resolver': { - typescript: {}, - }, + '@typescript-eslint': eslintPluginTypescript, + import: eslintPluginImportTypescript, + 'typescript-sort-keys': eslintPluginTypescriptSortKeys, }, rules: { ...eslintPluginTypescript.configs.recommended.rules, @@ -43,7 +39,13 @@ export default [ // Unable work with Global namespace 'no-undef': 'off', 'no-use-before-define': 'off', - } + }, + settings: { + ...eslintPluginImportTypescript.configs.typescript.settings, + 'import/resolver': { + typescript: {}, + }, + }, }, { files: ['typings/**/*.d.ts'], @@ -51,4 +53,4 @@ export default [ '@typescript-eslint/no-unused-vars': 'off', // Not work for type declaration file }, }, -] +]; diff --git a/packages/eslint-config/preset/yml.mjs b/packages/eslint-config/preset/yml.mjs index 7f3b2496..d60f54de 100644 --- a/packages/eslint-config/preset/yml.mjs +++ b/packages/eslint-config/preset/yml.mjs @@ -1,9 +1,9 @@ -import eslintPluginYml from "eslint-plugin-yml" -import eslintParserYml from "yaml-eslint-parser" +import eslintPluginYml from 'eslint-plugin-yml'; +import eslintParserYml from 'yaml-eslint-parser'; export default [ { - files: ['*.yml', '*.yaml'], + files: ['**/*.yml', '**/*.yaml'], languageOptions: { parser: eslintParserYml, }, @@ -15,5 +15,5 @@ export default [ 'yml/quotes': ['error', { prefer: 'single' }], 'yml/sort-keys': 'error', }, - } -] \ No newline at end of file + }, +]; diff --git a/packages/eslint-config/utils/file-patterns.mjs b/packages/eslint-config/utils/file-patterns.mjs index 5f1e23c1..d7e9b197 100644 --- a/packages/eslint-config/utils/file-patterns.mjs +++ b/packages/eslint-config/utils/file-patterns.mjs @@ -1,14 +1,23 @@ - export const typescriptJSXFileSuffixes = ['tsx', 'mtsx', 'ctsx']; export const jsJSXFileSuffixes = ['jsx', 'mjsx', 'cjsx']; -export const typescriptFileSuffixes = ['ts', 'mts', 'cts', ...typescriptJSXFileSuffixes]; +export const typescriptFileSuffixes = [ + 'ts', + 'mts', + 'cts', + ...typescriptJSXFileSuffixes, +]; export const jsFileSuffixes = ['js', 'cjs', 'mjs', ...jsJSXFileSuffixes]; -export const typescriptTestFilePatterns = typescriptFileSuffixes.map(ext => [`*.test.${ext}`, `*.spec.${ext}`]) - .flat(); -export const jsTestFilePatterns = jsFileSuffixes - .map(ext => [`*.test.${ext}`, `*.spec.${ext}`]) - .flat(); +export const typescriptTestFilePatterns = typescriptFileSuffixes + .map(ext => [`*.test.${ext}`, `*.spec.${ext}`]) + .flat(); +export const jsTestFilePatterns = jsFileSuffixes + .map(ext => [`*.test.${ext}`, `*.spec.${ext}`]) + .flat(); -export const jsJSXTestFilePatterns = jsJSXFileSuffixes.map(ext => [`*.test.${ext}`, `*.spec.${ext}`]).flat(); -export const typescriptJSXTestFilePattern = typescriptJSXFileSuffixes.map(ext => [`*.test.${ext}`, `*.spec.${ext}`]).flat(); \ No newline at end of file +export const jsJSXTestFilePatterns = jsJSXFileSuffixes + .map(ext => [`*.test.${ext}`, `*.spec.${ext}`]) + .flat(); +export const typescriptJSXTestFilePattern = typescriptJSXFileSuffixes + .map(ext => [`*.test.${ext}`, `*.spec.${ext}`]) + .flat(); diff --git a/packages/eslint-config/utils/has-config.mjs b/packages/eslint-config/utils/has-config.mjs index 23ef4e07..015e9a66 100644 --- a/packages/eslint-config/utils/has-config.mjs +++ b/packages/eslint-config/utils/has-config.mjs @@ -1,9 +1,12 @@ -import {promises as fs} from "node:fs" -import {path} from "ramda" +import { promises as fs } from 'node:fs'; + +import { path } from 'ramda'; + +import packageJsonMod from './package-json.mjs'; -import packageJsonMod from "./package-json.mjs" export async function hasConfig(config) { - const {packageJson, projectPath} = await packageJsonMod.readClosestPackageJson() + const { packageJson, projectPath } = + await packageJsonMod.readClosestPackageJson(); for (const c of config) { if (c.type === 'dependency') { const dependencyType = c.dependencyType || 'prod'; @@ -11,21 +14,23 @@ export async function hasConfig(config) { dev: 'devDependencies', peer: 'peerDependencies', prod: 'dependencies', - }[dependencyType] + }[dependencyType]; if (path([dependencyKey, c.dependency], packageJson) !== undefined) { return true; } } else if (c.type === 'file') { try { - await fs.access(`${projectPath}/${c.pattern}`, fs.constants.R_OK) + await fs.access(`${projectPath}/${c.pattern}`, fs.constants.R_OK); return true; - } catch (err) {} + } catch (err) { + return false; + } } else if (c.type === 'package.json') { - const {property, value} = c - if (path(property, packageJson) === value) { + const { property, value } = c; + if (path(property, packageJson) === value) { return true; } } } return false; -} \ No newline at end of file +} diff --git a/packages/eslint-config/utils/has-config.test.mjs b/packages/eslint-config/utils/has-config.test.mjs index 3362ac28..04206e0a 100644 --- a/packages/eslint-config/utils/has-config.test.mjs +++ b/packages/eslint-config/utils/has-config.test.mjs @@ -1,72 +1,109 @@ -import {describe, it} from "node:test" -import assert from "node:assert" -import {dirname, basename} from "node:path" +import assert from 'node:assert'; +import { basename, dirname } from 'node:path'; +import { describe, it } from 'node:test'; describe('has config', () => { - it('should mock package json', async (t) => { - const {default : packageJSON} = await import("./package-json.mjs") - const mock = t.mock.method(packageJSON, 'readClosestPackageJson',() => { - return Promise.resolve({ - packageJson: {type: 'module'} - })}); - const {hasConfig} = await import('./has-config.mjs') - const hasTypeModule = await hasConfig([{type: 'package.json', property: ['type'], value: 'module'}]) - assert.strictEqual(hasTypeModule, true, 'should be true') - }) + it('should mock package json', async () => { + const { hasConfig } = await import('./has-config.mjs'); + const hasTypeModule = await hasConfig([ + { property: ['type'], type: 'package.json', value: 'module' }, + ]); + assert.strictEqual(hasTypeModule, true, 'should be true'); + }); - describe('check package json contain dependency', () => Promise.all([{ - dependencyType: 'prod', - dependencyKey: 'dependencies' - }, + describe('check package json contain dependency', () => + Promise.all( + [ + { + dependencyKey: 'dependencies', + dependencyType: 'prod', + }, { - dependencyType: 'dev', - dependencyKey: 'devDependencies' + dependencyKey: 'devDependencies', + dependencyType: 'dev', }, { - dependencyType: 'peer', - dependencyKey: 'peerDependencies' - }].map(({dependencyType,dependencyKey})=> it(`should able to check package json contain react in ${dependencyType} dependency`, async (t) => { - const {default : packageJSON} = await import("./package-json.mjs") - t.mock.method(packageJSON, 'readClosestPackageJson',() => { + dependencyKey: 'peerDependencies', + dependencyType: 'peer', + }, + ].map(({ dependencyKey, dependencyType }) => + it(`should able to check package json contain react in ${dependencyType} dependency`, async t => { + const { default: packageJSON } = await import('./package-json.mjs'); + t.mock.method(packageJSON, 'readClosestPackageJson', () => { return Promise.resolve({ - packageJson: {[dependencyKey]: { - react: '17.0.2' - }} - })}); - const {hasConfig} = await import('./has-config.mjs') - const hasDependency = await hasConfig([{type: 'dependency', dependencyType , dependency: 'react'}]) - assert.strictEqual(hasDependency, true, `should return true when package json contain react in ${dependencyType} dependency`) - })))) + packageJson: { + [dependencyKey]: { + react: '17.0.2', + }, + }, + }); + }); + const { hasConfig } = await import('./has-config.mjs'); + const hasDependency = await hasConfig([ + { dependency: 'react', dependencyType, type: 'dependency' }, + ]); + assert.strictEqual( + hasDependency, + true, + `should return true when package json contain react in ${dependencyType} dependency`, + ); + }), + ), + )); - it('should able to check file exist', async (t) => { - const {default : packageJSON} = await import("./package-json.mjs") - const currentFilePath = new URL(import.meta.url) - const [currentFileDir, currentFileName] = [dirname(currentFilePath.pathname), basename(currentFilePath.pathname)] - t.mock.method(packageJSON, 'readClosestPackageJson',() => { - return Promise.resolve({ - packageJson: {dependencies: { - react: '17.0.2' - }}, - projectPath: currentFileDir - })}); - const {hasConfig} = await import('./has-config.mjs') - const hasFile = await hasConfig([{type: 'file', pattern: currentFileName}]) - assert.strictEqual(hasFile, true, `should return true when directory contain ${currentFileName} file`) - }) + it('should able to check file exist', async t => { + const { default: packageJSON } = await import('./package-json.mjs'); + const currentFilePath = new URL(import.meta.url); + const [currentFileDir, currentFileName] = [ + dirname(currentFilePath.pathname), + basename(currentFilePath.pathname), + ]; + t.mock.method(packageJSON, 'readClosestPackageJson', () => { + return Promise.resolve({ + packageJson: { + dependencies: { + react: '17.0.2', + }, + }, + projectPath: currentFileDir, + }); + }); + const { hasConfig } = await import('./has-config.mjs'); + const hasFile = await hasConfig([ + { pattern: currentFileName, type: 'file' }, + ]); + assert.strictEqual( + hasFile, + true, + `should return true when directory contain ${currentFileName} file`, + ); + }); - it('should able to property value in package json', async (t) => { - const {default : packageJSON} = await import("./package-json.mjs") - const currentFilePath = new URL(import.meta.url) - const [currentFileDir, currentFileName] = [dirname(currentFilePath.pathname), basename(currentFilePath.pathname)] - t.mock.method(packageJSON, 'readClosestPackageJson',() => { - return Promise.resolve({ - packageJson: {dependencies: { - react: '17.0.2' - }}, - projectPath: currentFileDir - })}); - const {hasConfig} = await import('./has-config.mjs') - const hasFile = await hasConfig([{type: 'file', pattern: currentFileName}]) - assert.strictEqual(hasFile, true, `should return true when directory contain ${currentFileName} file`) - }) -}) \ No newline at end of file + it('should able to property value in package json', async t => { + const { default: packageJSON } = await import('./package-json.mjs'); + const currentFilePath = new URL(import.meta.url); + const [currentFileDir, currentFileName] = [ + dirname(currentFilePath.pathname), + basename(currentFilePath.pathname), + ]; + t.mock.method(packageJSON, 'readClosestPackageJson', () => { + return Promise.resolve({ + packageJson: { + dependencies: { + react: '17.0.2', + }, + }, + projectPath: currentFileDir, + }); + }); + const { hasConfig } = await import('./has-config.mjs'); + const hasFile = await hasConfig([ + { pattern: currentFileName, type: 'file' }, + ]); + assert.strictEqual( + hasFile, + true, + `should return true when directory contain ${currentFileName} file`, + ); + }); +}); diff --git a/packages/eslint-config/utils/is-default-esm.mjs b/packages/eslint-config/utils/is-default-esm.mjs index 69d9421b..5ee9ed3e 100644 --- a/packages/eslint-config/utils/is-default-esm.mjs +++ b/packages/eslint-config/utils/is-default-esm.mjs @@ -1,3 +1,4 @@ -import {hasConfig} from "./has-config.mjs"; +import { hasConfig } from './has-config.mjs'; -export const isDefaultEsm = () => hasConfig([{type: 'package.json', property: ['type'], value: 'module'}]) +export const isDefaultEsm = () => + hasConfig([{ property: ['type'], type: 'package.json', value: 'module' }]); diff --git a/packages/eslint-config/utils/package-json.mjs b/packages/eslint-config/utils/package-json.mjs index 4129d3c9..21de0564 100644 --- a/packages/eslint-config/utils/package-json.mjs +++ b/packages/eslint-config/utils/package-json.mjs @@ -1,18 +1,21 @@ -import {readPackageUp} from "read-package-up"; -const {packageJson, projectPath} = await readPackageUp({ - cwd: process.cwd(), +import { readPackageUp } from 'read-package-up'; + +const { packageJson, projectPath } = await readPackageUp({ + cwd: process.cwd(), }); export async function readClosestPackageJson() { - return { - packageJson, projectPath - } + return { + packageJson, + projectPath, + }; } export default { - readClosestPackageJson: async () => { - return { - packageJson, projectPath - } - } -} \ No newline at end of file + readClosestPackageJson: async () => { + return { + packageJson, + projectPath, + }; + }, +}; diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 25af8006..b2d060ee 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -3,7 +3,7 @@ "prettier-plugin-tailwindcss": "0.5.11" }, "engines": { - "node": ">=14", + "node": ">=18", "yarn": "Use npm" }, "exports": { diff --git a/packages/tsconfig/package.json b/packages/tsconfig/package.json index f064b269..70889d3e 100644 --- a/packages/tsconfig/package.json +++ b/packages/tsconfig/package.json @@ -6,7 +6,7 @@ "typescript": "5.3.3" }, "engines": { - "node": ">=14", + "node": ">=18", "yarn": "Use npm" }, "files": [