diff --git a/src/main/java/tech/jhipster/lite/generator/client/react/core/domain/ReactCoreModulesFactory.java b/src/main/java/tech/jhipster/lite/generator/client/react/core/domain/ReactCoreModulesFactory.java index a28e5386f1d..4be258b8613 100644 --- a/src/main/java/tech/jhipster/lite/generator/client/react/core/domain/ReactCoreModulesFactory.java +++ b/src/main/java/tech/jhipster/lite/generator/client/react/core/domain/ReactCoreModulesFactory.java @@ -1,5 +1,8 @@ package tech.jhipster.lite.generator.client.react.core.domain; +import static tech.jhipster.lite.generator.typescript.common.domain.EslintShortcuts.eslintTypescriptRule; +import static tech.jhipster.lite.generator.typescript.common.domain.TsConfigShortcuts.tsConfigCompilerOption; +import static tech.jhipster.lite.generator.typescript.common.domain.VitestShortcuts.vitestCoverageExclusion; import static tech.jhipster.lite.module.domain.JHipsterModule.JHipsterModuleBuilder; import static tech.jhipster.lite.module.domain.JHipsterModule.LINE_BREAK; import static tech.jhipster.lite.module.domain.JHipsterModule.from; @@ -19,13 +22,11 @@ import static tech.jhipster.lite.module.domain.replacement.ReplacementCondition.always; import java.util.function.Consumer; -import tech.jhipster.lite.module.domain.Indentation; import tech.jhipster.lite.module.domain.JHipsterModule; import tech.jhipster.lite.module.domain.file.JHipsterDestination; import tech.jhipster.lite.module.domain.file.JHipsterSource; import tech.jhipster.lite.module.domain.npm.NpmLazyInstaller; import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties; -import tech.jhipster.lite.module.domain.replacement.MandatoryReplacer; public class ReactCoreModulesFactory { @@ -142,10 +143,6 @@ private Consumer patchEslintConfig(JHipsterModuleProperti .add( regex("[ \\t]+quotes: \\['error', 'single', \\{ avoidEscape: true }],"), """ - \t\t\t'react/react-in-jsx-scope': 'off', - \t\t\t'@typescript-eslint/no-explicit-any': 'off', - \t\t\t'@typescript-eslint/await-thenable': 'off', - \t\t\t'@typescript-eslint/consistent-type-imports': 'error', \t\t\t'@typescript-eslint/no-misused-promises': [ \t\t\t\t'error', \t\t\t\t{ @@ -155,7 +152,11 @@ private Consumer patchEslintConfig(JHipsterModuleProperti """.replace("\t", properties.indentation().spaces()) ) .and() - .and(); + .and() + .apply(eslintTypescriptRule("'@typescript-eslint/consistent-type-imports': 'error'", properties.indentation())) + .apply(eslintTypescriptRule("'@typescript-eslint/await-thenable': 'off'", properties.indentation())) + .apply(eslintTypescriptRule("'@typescript-eslint/no-explicit-any': 'off'", properties.indentation())) + .apply(eslintTypescriptRule("'react/react-in-jsx-scope': 'off'", properties.indentation())); //@formatter:on } @@ -167,20 +168,15 @@ private Consumer patchTsConfig(JHipsterModuleProperties p .mandatoryReplacements() .in(path("tsconfig.json")) .add(text("@tsconfig/recommended/tsconfig.json"), "@tsconfig/vite-react/tsconfig.json") - .add(tsConfigCompilerOption("composite", false, properties.indentation())) - .add(tsConfigCompilerOption("forceConsistentCasingInFileNames", true, properties.indentation())) - .add(tsConfigCompilerOption("allowSyntheticDefaultImports", true, properties.indentation())) .add(text(DEFAULT_TSCONFIG_PATH), pathsReplacement) .and() - .and(); + .and() + .apply(tsConfigCompilerOption("composite", false, properties.indentation())) + .apply(tsConfigCompilerOption("forceConsistentCasingInFileNames", true, properties.indentation())) + .apply(tsConfigCompilerOption("allowSyntheticDefaultImports", true, properties.indentation())); //@formatter:on } - private static MandatoryReplacer tsConfigCompilerOption(String optionName, boolean optionValue, Indentation indentation) { - String compilerOption = indentation.times(2) + "\"%s\": %s,".formatted(optionName, optionValue); - return new MandatoryReplacer(lineAfterRegex("\"compilerOptions\":"), compilerOption); - } - private Consumer patchVitestConfig(JHipsterModuleProperties properties) { //@formatter:off return moduleBuilder -> moduleBuilder @@ -189,16 +185,10 @@ private Consumer patchVitestConfig(JHipsterModuleProperti .add(lineAfterRegex("from 'vitest/config';"), "import react from '@vitejs/plugin-react';") .add(text("plugins: ["), "plugins: [react(), ") .add(text("environment: 'node',"), "environment: 'jsdom',") - .add(vitestCoverageExclusion("src/main/webapp/app/index.tsx")) - .add(vitestCoverageExclusion("src/main/webapp/app/injections.ts")) - .and(); + .and() + .and() + .apply(vitestCoverageExclusion("src/main/webapp/app/index.tsx")) + .apply(vitestCoverageExclusion("src/main/webapp/app/injections.ts")); //@formatter:on } - - private static MandatoryReplacer vitestCoverageExclusion(String filePattern) { - return new MandatoryReplacer( - text("(configDefaults.coverage.exclude as string[])"), - "(configDefaults.coverage.exclude as string[])" + ", '%s'".formatted(filePattern) - ); - } } diff --git a/src/main/java/tech/jhipster/lite/generator/client/react/i18n/domain/ReactI18nModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/client/react/i18n/domain/ReactI18nModuleFactory.java index 6243dc7f596..e9c191dc119 100644 --- a/src/main/java/tech/jhipster/lite/generator/client/react/i18n/domain/ReactI18nModuleFactory.java +++ b/src/main/java/tech/jhipster/lite/generator/client/react/i18n/domain/ReactI18nModuleFactory.java @@ -1,5 +1,6 @@ package tech.jhipster.lite.generator.client.react.i18n.domain; +import static tech.jhipster.lite.generator.typescript.common.domain.VitestShortcuts.vitestCoverageExclusion; import static tech.jhipster.lite.module.domain.JHipsterModule.LINE_BREAK; import static tech.jhipster.lite.module.domain.JHipsterModule.append; import static tech.jhipster.lite.module.domain.JHipsterModule.from; @@ -75,10 +76,8 @@ public JHipsterModule buildModule(JHipsterModuleProperties properties) { }); });""" ) .and() - .in(path("./vitest.config.ts")) - .add(lineAfterText("'src/main/webapp/app/index.tsx',"), properties.indentation().times(4) + "'src/main/webapp/app/i18n.ts',") - .and() .and() + .apply(vitestCoverageExclusion("src/main/webapp/app/i18n.ts")) .build(); //@formatter:off } diff --git a/src/main/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactory.java b/src/main/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactory.java index b1b8825ab6a..ff246820bd4 100644 --- a/src/main/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactory.java +++ b/src/main/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactory.java @@ -1,5 +1,8 @@ package tech.jhipster.lite.generator.client.vue.core.domain; +import static tech.jhipster.lite.generator.typescript.common.domain.EslintShortcuts.eslintTypescriptRule; +import static tech.jhipster.lite.generator.typescript.common.domain.TsConfigShortcuts.tsConfigCompilerOption; +import static tech.jhipster.lite.generator.typescript.common.domain.VitestShortcuts.vitestCoverageExclusion; import static tech.jhipster.lite.module.domain.JHipsterModule.JHipsterModuleBuilder; import static tech.jhipster.lite.module.domain.JHipsterModule.documentationTitle; import static tech.jhipster.lite.module.domain.JHipsterModule.from; @@ -18,13 +21,11 @@ import static tech.jhipster.lite.module.domain.npm.JHLiteNpmVersionSource.VUE; import java.util.function.Consumer; -import tech.jhipster.lite.module.domain.Indentation; import tech.jhipster.lite.module.domain.JHipsterModule; import tech.jhipster.lite.module.domain.file.JHipsterDestination; import tech.jhipster.lite.module.domain.file.JHipsterSource; import tech.jhipster.lite.module.domain.npm.NpmLazyInstaller; import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties; -import tech.jhipster.lite.module.domain.replacement.MandatoryReplacer; import tech.jhipster.lite.shared.error.domain.Assert; public class VueModulesFactory { @@ -122,7 +123,7 @@ public JHipsterModule buildVueModule(JHipsterModuleProperties properties) { .and() .apply(patchEslintConfig(properties)) .apply(patchTsConfig(properties)) - .apply(patchVitestConfig(properties)) + .apply(patchVitestConfig()) .build(); //@formatter:on } @@ -146,39 +147,30 @@ private Consumer patchEslintConfig(JHipsterModuleProperti .add(lineAfterRegex("from '@eslint/js'"), "import vue from 'eslint-plugin-vue';") .add(lineAfterRegex("...typescript.configs.recommended"), vuePluginConfig) .add(text("files: ['src/*/webapp/**/*.ts']"), "files: ['src/*/webapp/**/*.vue', 'src/*/webapp/**/*.ts']") - .add(eslintTypescriptVueRule("'vue/html-self-closing': 'off',", properties.indentation())) - .add(eslintTypescriptVueRule("'@typescript-eslint/no-explicit-any': 'off',", properties.indentation())) - .add(eslintTypescriptVueRule("'@typescript-eslint/no-empty-object-type': 'off',", properties.indentation())) - .add(eslintTypescriptVueRule("'@typescript-eslint/consistent-type-imports': 'error',", properties.indentation())) .and() - .and(); + .and() + .apply(eslintTypescriptRule("'vue/html-self-closing': 'off'", properties.indentation())) + .apply(eslintTypescriptRule("'@typescript-eslint/no-explicit-any': 'off'", properties.indentation())) + .apply(eslintTypescriptRule("'@typescript-eslint/no-empty-object-type': 'off'", properties.indentation())) + .apply(eslintTypescriptRule("'@typescript-eslint/consistent-type-imports': 'error'", properties.indentation())); //@formatter:on } - private static MandatoryReplacer eslintTypescriptVueRule(String rule, Indentation indentation) { - return new MandatoryReplacer(lineAfterRegex("quotes: \\['error', 'single'"), indentation.times(3) + rule); - } - private Consumer patchTsConfig(JHipsterModuleProperties properties) { //@formatter:off return moduleBuilder -> moduleBuilder .mandatoryReplacements() .in(path("tsconfig.json")) .add(text("@tsconfig/recommended/tsconfig.json"), "@vue/tsconfig/tsconfig.dom.json") - .add(tsConfigCompilerOption("sourceMap", true, properties.indentation())) - .add(tsConfigCompilerOption("allowJs", true, properties.indentation())) .add(text("\"types\": ["), "\"types\": [\"vite/client\", ") .and() - .and(); + .and() + .apply(tsConfigCompilerOption("sourceMap", true, properties.indentation())) + .apply(tsConfigCompilerOption("allowJs", true, properties.indentation())); //@formatter:on } - private static MandatoryReplacer tsConfigCompilerOption(String optionName, boolean optionValue, Indentation indentation) { - String compilerOption = indentation.times(2) + "\"%s\": %s,".formatted(optionName, optionValue); - return new MandatoryReplacer(lineAfterRegex("\"compilerOptions\":"), compilerOption); - } - - private Consumer patchVitestConfig(JHipsterModuleProperties properties) { + private Consumer patchVitestConfig() { //@formatter:off return moduleBuilder -> moduleBuilder .mandatoryReplacements() @@ -186,21 +178,15 @@ private Consumer patchVitestConfig(JHipsterModuleProperti .add(lineAfterRegex("from 'vitest/config';"), "import vue from '@vitejs/plugin-vue';") .add(text("plugins: ["), "plugins: [vue(), ") .add(text("environment: 'node',"), "environment: 'jsdom',") - .add(vitestCoverageExclusion("src/main/webapp/**/*.component.ts")) - .add(vitestCoverageExclusion("src/main/webapp/app/router.ts")) - .add(vitestCoverageExclusion("src/main/webapp/app/injections.ts")) - .add(vitestCoverageExclusion("src/main/webapp/app/main.ts")) - .and(); + .and() + .and() + .apply(vitestCoverageExclusion("src/main/webapp/**/*.component.ts")) + .apply(vitestCoverageExclusion("src/main/webapp/app/router.ts")) + .apply(vitestCoverageExclusion("src/main/webapp/app/injections.ts")) + .apply(vitestCoverageExclusion("src/main/webapp/app/main.ts")); //@formatter:on } - private static MandatoryReplacer vitestCoverageExclusion(String filePattern) { - return new MandatoryReplacer( - text("(configDefaults.coverage.exclude as string[])"), - "(configDefaults.coverage.exclude as string[])" + ", '" + filePattern + "'" - ); - } - public JHipsterModule buildPiniaModule(JHipsterModuleProperties properties) { Assert.notNull("properties", properties); diff --git a/src/main/java/tech/jhipster/lite/generator/typescript/common/domain/EslintShortcuts.java b/src/main/java/tech/jhipster/lite/generator/typescript/common/domain/EslintShortcuts.java new file mode 100644 index 00000000000..9b963a98a91 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/typescript/common/domain/EslintShortcuts.java @@ -0,0 +1,29 @@ +package tech.jhipster.lite.generator.typescript.common.domain; + +import static tech.jhipster.lite.module.domain.JHipsterModule.lineAfterRegex; +import static tech.jhipster.lite.module.domain.JHipsterModule.path; + +import java.util.function.Consumer; +import tech.jhipster.lite.module.domain.Indentation; +import tech.jhipster.lite.module.domain.JHipsterModule; +import tech.jhipster.lite.module.domain.replacement.MandatoryReplacer; + +public final class EslintShortcuts { + + private EslintShortcuts() {} + + public static Consumer eslintTypescriptRule(String rule, Indentation indentation) { + //@formatter:off + return moduleBuilder -> moduleBuilder + .mandatoryReplacements() + .in(path("eslint.config.js")) + .add(eslintTypescriptVueRuleReplacement(rule, indentation)) + .and() + .and(); + //@formatter:on + } + + private static MandatoryReplacer eslintTypescriptVueRuleReplacement(String rule, Indentation indentation) { + return new MandatoryReplacer(lineAfterRegex("rules: \\{"), indentation.times(3) + rule + ","); + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/typescript/common/domain/TsConfigShortcuts.java b/src/main/java/tech/jhipster/lite/generator/typescript/common/domain/TsConfigShortcuts.java new file mode 100644 index 00000000000..03de6d6d0d3 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/typescript/common/domain/TsConfigShortcuts.java @@ -0,0 +1,33 @@ +package tech.jhipster.lite.generator.typescript.common.domain; + +import static tech.jhipster.lite.module.domain.JHipsterModule.lineAfterRegex; +import static tech.jhipster.lite.module.domain.JHipsterModule.path; + +import java.util.function.Consumer; +import tech.jhipster.lite.module.domain.Indentation; +import tech.jhipster.lite.module.domain.JHipsterModule; +import tech.jhipster.lite.module.domain.replacement.MandatoryReplacer; + +public final class TsConfigShortcuts { + + private TsConfigShortcuts() {} + + public static Consumer tsConfigCompilerOption( + String optionName, + boolean optionValue, + Indentation indentation + ) { + //@formatter:off + return moduleBuilder -> moduleBuilder + .mandatoryReplacements() + .in(path("tsconfig.json")) + .add(tsConfigCompilerOptionReplacement(optionName, optionValue, indentation)) + .and(); + //@formatter:on + } + + private static MandatoryReplacer tsConfigCompilerOptionReplacement(String optionName, boolean optionValue, Indentation indentation) { + String compilerOption = indentation.times(2) + "\"%s\": %s,".formatted(optionName, optionValue); + return new MandatoryReplacer(lineAfterRegex("\"compilerOptions\":"), compilerOption); + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/typescript/common/domain/VitestShortcuts.java b/src/main/java/tech/jhipster/lite/generator/typescript/common/domain/VitestShortcuts.java new file mode 100644 index 00000000000..624c7767d49 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/typescript/common/domain/VitestShortcuts.java @@ -0,0 +1,29 @@ +package tech.jhipster.lite.generator.typescript.common.domain; + +import static tech.jhipster.lite.module.domain.JHipsterModule.path; +import static tech.jhipster.lite.module.domain.JHipsterModule.text; + +import java.util.function.Consumer; +import tech.jhipster.lite.module.domain.JHipsterModule; +import tech.jhipster.lite.module.domain.replacement.MandatoryReplacer; + +public final class VitestShortcuts { + + private VitestShortcuts() {} + + public static Consumer vitestCoverageExclusion(String exclusionFilePattern) { + //@formatter:off + return moduleBuilder -> moduleBuilder + .mandatoryReplacements() + .in(path("vitest.config.ts")) + .add(vitestCoverageExclusionReplacement(exclusionFilePattern)); + //@formatter:on + } + + private static MandatoryReplacer vitestCoverageExclusionReplacement(String filePattern) { + return new MandatoryReplacer( + text("(configDefaults.coverage.exclude as string[])"), + "(configDefaults.coverage.exclude as string[])" + ", '%s'".formatted(filePattern) + ); + } +} diff --git a/src/main/java/tech/jhipster/lite/generator/typescript/common/package-info.java b/src/main/java/tech/jhipster/lite/generator/typescript/common/package-info.java new file mode 100644 index 00000000000..1173f1ca90f --- /dev/null +++ b/src/main/java/tech/jhipster/lite/generator/typescript/common/package-info.java @@ -0,0 +1,2 @@ +@tech.jhipster.lite.SharedKernel +package tech.jhipster.lite.generator.typescript.common; diff --git a/src/test/resources/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactoryTest.shouldCreateVueModule.eslint.config.js.approved.txt b/src/test/resources/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactoryTest.shouldCreateVueModule.eslint.config.js.approved.txt index 275694c9617..7daab41b1e8 100644 --- a/src/test/resources/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactoryTest.shouldCreateVueModule.eslint.config.js.approved.txt +++ b/src/test/resources/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactoryTest.shouldCreateVueModule.eslint.config.js.approved.txt @@ -30,11 +30,11 @@ export default typescript.config( globals: { ...globals.browser }, }, rules: { - quotes: ['error', 'single', { avoidEscape: true }], '@typescript-eslint/consistent-type-imports': 'error', '@typescript-eslint/no-empty-object-type': 'off', '@typescript-eslint/no-explicit-any': 'off', 'vue/html-self-closing': 'off', + quotes: ['error', 'single', { avoidEscape: true }], }, }, );