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 19ba80b4523..39055c1524c 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,14 +1,18 @@ package tech.jhipster.lite.generator.client.vue.core.domain; import static tech.jhipster.lite.module.domain.JHipsterModule.*; -import static tech.jhipster.lite.module.domain.packagejson.NodeModuleFormat.MODULE; import static tech.jhipster.lite.module.domain.packagejson.VersionSource.COMMON; import static tech.jhipster.lite.module.domain.packagejson.VersionSource.VUE; +import static tech.jhipster.lite.module.domain.replacement.ReplacementCondition.notContainingReplacement; +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.properties.JHipsterModuleProperties; +import tech.jhipster.lite.module.domain.replacement.MandatoryReplacer; +import tech.jhipster.lite.module.domain.replacement.TextReplacer; import tech.jhipster.lite.shared.error.domain.Assert; public class VueModulesFactory { @@ -17,7 +21,6 @@ public class VueModulesFactory { private static final JHipsterSource APP_SOURCE = from("client/vue/webapp/app"); private static final JHipsterSource DOCUMENTATION_SOURCE = SOURCE.append("documentation"); private static final JHipsterSource IMAGE_SOURCE = SOURCE.append("webapp/content/images"); - private static final JHipsterSource SOURCE_COMMON = from("client/common"); private static final JHipsterDestination MAIN_DESTINATION = to("src/main/webapp/app"); private static final JHipsterDestination TEST_DESTINATION = to("src/test/webapp"); @@ -42,55 +45,33 @@ public JHipsterModule buildVueModule(JHipsterModuleProperties properties) { .preCommitActions(stagedFilesFilter("{src/**/,}*.{ts,vue}"), preCommitCommands("eslint --fix", "prettier --write")) .documentation(documentationTitle("Vue"), DOCUMENTATION_SOURCE.file("vue.md")) .packageJson() - .type(MODULE) + .removeDevDependency(packageName("@tsconfig/recommended")) .addDependency(packageName("vue"), VUE) .addDependency(packageName("axios"), VUE) .addDependency(packageName("vue-router"), VUE) - .addDevDependency(packageName("@typescript-eslint/parser"), COMMON) + .addDependency(packageName("piqure"), VUE) .addDevDependency(packageName("@vitejs/plugin-vue"), VUE) - .addDevDependency(packageName("typescript-eslint"), COMMON) - .addDevDependency(packageName("globals"), COMMON) .addDevDependency(packageName("@vue/test-utils"), VUE) .addDevDependency(packageName("@vue/tsconfig"), VUE) - .addDevDependency(packageName("@vitest/coverage-istanbul"), COMMON) - .addDevDependency(packageName("eslint"), COMMON) - .addDevDependency(packageName("eslint-config-prettier"), COMMON) .addDevDependency(packageName("eslint-plugin-vue"), VUE) .addDevDependency(packageName("jsdom"), COMMON) - .addDevDependency(packageName("typescript"), COMMON) .addDevDependency(packageName("vite"), COMMON) - .addDevDependency(packageName("vite-tsconfig-paths"), COMMON) - .addDevDependency(packageName("vitest"), COMMON) - .addDevDependency(packageName("vitest-sonar-reporter"), COMMON) .addDevDependency(packageName("vue-tsc"), VUE) .addDevDependency(packageName("@types/sinon"), VUE) .addDevDependency(packageName("sinon"), VUE) - .addDevDependency(packageName("npm-run-all2"), COMMON) .addScript(scriptKey("build"), scriptCommand("npm-run-all build:*")) .addScript(scriptKey("build:tsc"), scriptCommand("vue-tsc -p tsconfig.build.json --noEmit")) .addScript(scriptKey("build:vite"), scriptCommand("vite build --emptyOutDir")) .addScript(scriptKey("dev"), scriptCommand("npm-run-all --parallel dev:*")) .addScript(scriptKey("dev:vite"), scriptCommand("vite")) - .addScript(scriptKey("watch"), scriptCommand("npm-run-all --parallel watch:*")) - .addDevDependency(packageName("piqure"), VUE) - .addScript(scriptKey("lint"), scriptCommand("eslint .")) .addScript(scriptKey("preview"), scriptCommand("vite preview")) .addScript(scriptKey("start"), scriptCommand("vite")) .addScript(scriptKey("watch:tsc"), scriptCommand("npm run build:tsc -- --watch")) - .addScript(scriptKey("test"), scriptCommand("npm run watch:test")) - .addScript(scriptKey("watch:test"), scriptCommand("vitest --")) - .addScript(scriptKey("test:coverage"), scriptCommand("vitest run --coverage")) .and() .files() - .add(SOURCE.template("eslint.config.js.mustache"), to("eslint.config.js")) - .add(SOURCE.file("tsconfig.json"), to("tsconfig.json")) .add(SOURCE.file("tsconfig.build.json"), to("tsconfig.build.json")) .batch(SOURCE, to(".")) .addTemplate("vite.config.ts") - .addTemplate("vitest.config.ts") - .and() - .batch(SOURCE_COMMON, to(".")) - .addFile(".npmrc") .and() .add(SOURCE.template("webapp/index.html"), to("src/main/webapp/index.html")) .batch(APP_SOURCE, MAIN_DESTINATION) @@ -115,10 +96,84 @@ public JHipsterModule buildVueModule(JHipsterModuleProperties properties) { .add(APP_SOURCE.template("test/webapp/unit/shared/http/infrastructure/secondary/AxiosStub.ts.mustache"), TEST_DESTINATION.append("unit/shared/http/infrastructure/secondary/AxiosStub.ts")) .add(APP_SOURCE.template("test/webapp/unit/router/infrastructure/primary/HomeRouter.spec.ts.mustache"), TEST_DESTINATION.append("unit/router/infrastructure/primary/HomeRouter.spec.ts")) .and() + .apply(patchEslintConfig(properties)) + .apply(patchTsConfig(properties)) + .apply(patchVitestConfig(properties)) .build(); //@formatter:on } + private Consumer patchEslintConfig(JHipsterModuleProperties properties) { + String vuePluginConfig = + """ + \t...vue.configs['flat/recommended'], + \t{ + \t\tfiles: ['**/*.vue'], + \t\tlanguageOptions: { + \t\t\tparserOptions: { parser: '@typescript-eslint/parser' }, + \t\t\tglobals: { ...globals.browser }, + \t\t}, + \t},\ + """.replace("\t", properties.indentation().spaces()); + //@formatter:off + return moduleBuilder -> moduleBuilder + .mandatoryReplacements() + .in(path("eslint.config.js")) + .add(lineAfterRegex("from 'typescript-eslint'"), "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())) + .and() + .and(); + //@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(new TextReplacer(notContainingReplacement(), "\"types\": ["), "\"types\": [\"vite/client\", ") + .and() + .and(); + //@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 + .mandatoryReplacements() + .in(path("vitest.config.ts")) + .add(lineAfterRegex("from 'vitest/config';"), "import vue from '@vitejs/plugin-vue';") + .add(new TextReplacer(notContainingReplacement(), "plugins: ["), "plugins: [vue(), ") + .add(text("environment: 'node',"), "environment: 'jsdom',") + .add(vitestCoverageExclusion(properties,"src/main/webapp/**/*.component.ts")) + .add(vitestCoverageExclusion(properties,"src/main/webapp/app/router.ts")) + .add(vitestCoverageExclusion(properties,"src/main/webapp/app/injections.ts")) + .add(vitestCoverageExclusion(properties,"src/main/webapp/app/main.ts")) + .and(); + //@formatter:on + } + + private static MandatoryReplacer vitestCoverageExclusion(JHipsterModuleProperties properties, String filePattern) { + Indentation indentation = properties.indentation(); + return new MandatoryReplacer(lineAfterRegex("configDefaults.coverage.exclude"), indentation.times(4) + "'" + filePattern + "',"); + } + public JHipsterModule buildPiniaModule(JHipsterModuleProperties properties) { Assert.notNull("properties", properties); diff --git a/src/main/java/tech/jhipster/lite/generator/client/vue/core/infrastructure/primary/VueModuleConfiguration.java b/src/main/java/tech/jhipster/lite/generator/client/vue/core/infrastructure/primary/VueModuleConfiguration.java index 0b5baf0fac7..412fe160780 100644 --- a/src/main/java/tech/jhipster/lite/generator/client/vue/core/infrastructure/primary/VueModuleConfiguration.java +++ b/src/main/java/tech/jhipster/lite/generator/client/vue/core/infrastructure/primary/VueModuleConfiguration.java @@ -19,7 +19,7 @@ JHipsterModuleResource vueCoreModule(VueApplicationService vue) { .slug(VUE_CORE) .propertiesDefinition(JHipsterModulePropertiesDefinition.builder().addIndentation().build()) .apiDoc("Frontend - Vue", "Add Vue+Vite") - .organization(JHipsterModuleOrganization.builder().feature(CLIENT_CORE).addDependency(INIT).addDependency(PRETTIER).build()) + .organization(JHipsterModuleOrganization.builder().feature(CLIENT_CORE).addDependency(TYPESCRIPT).addDependency(PRETTIER).build()) .tags("client", "init", "vue") .factory(vue::buildVueModule); } diff --git a/src/main/java/tech/jhipster/lite/generator/typescript/core/domain/TypescriptModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/typescript/core/domain/TypescriptModuleFactory.java index 100acd2d94a..846154ab34e 100644 --- a/src/main/java/tech/jhipster/lite/generator/typescript/core/domain/TypescriptModuleFactory.java +++ b/src/main/java/tech/jhipster/lite/generator/typescript/core/domain/TypescriptModuleFactory.java @@ -12,6 +12,7 @@ public class TypescriptModuleFactory { private static final JHipsterSource SOURCE = from("typescript"); + private static final JHipsterSource SOURCE_COMMON = from("client/common"); public JHipsterModule buildModule(JHipsterModuleProperties properties) { Assert.notNull("properties", properties); @@ -27,7 +28,6 @@ public JHipsterModule buildModule(JHipsterModuleProperties properties) { .addDevDependency(packageName("@vitest/coverage-istanbul"), COMMON) .addDevDependency(packageName("eslint"), COMMON) .addDevDependency(packageName("eslint-config-prettier"), COMMON) - .addDevDependency(packageName("eslint-plugin-import-x"), COMMON) .addDevDependency(packageName("globals"), COMMON) .addDevDependency(packageName("npm-run-all2"), COMMON) .addDevDependency(packageName("typescript-eslint"), COMMON) @@ -42,6 +42,9 @@ public JHipsterModule buildModule(JHipsterModuleProperties properties) { .addScript(scriptKey("watch:test"), scriptCommand("vitest --")) .and() .files() + .batch(SOURCE_COMMON, to(".")) + .addFile(".npmrc") + .and() .batch(SOURCE, to(".")) .addFile("tsconfig.json") .addTemplate("vitest.config.ts") diff --git a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java index dbf6231e28c..f48c7892227 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java +++ b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java @@ -1,13 +1,12 @@ package tech.jhipster.lite.module.domain; -import static tech.jhipster.lite.module.domain.replacement.ReplacementCondition.*; +import static tech.jhipster.lite.module.domain.replacement.ReplacementCondition.always; +import static tech.jhipster.lite.module.domain.replacement.ReplacementCondition.notContainingReplacement; import java.nio.file.Paths; -import java.util.Collection; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; +import java.util.function.Consumer; import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Stream; @@ -22,41 +21,29 @@ import tech.jhipster.lite.module.domain.gitignore.JHipsterModuleGitIgnore.JHipsterModuleGitIgnoreBuilder; import tech.jhipster.lite.module.domain.gradleconfiguration.JHipsterModuleGradleConfigurations; import tech.jhipster.lite.module.domain.gradleconfiguration.JHipsterModuleGradleConfigurations.JHipsterModuleGradleConfigurationBuilder; -import tech.jhipster.lite.module.domain.gradleplugin.GradleCommunityPlugin; +import tech.jhipster.lite.module.domain.gradleplugin.*; import tech.jhipster.lite.module.domain.gradleplugin.GradleCommunityPlugin.GradleCommunityPluginIdBuilder; -import tech.jhipster.lite.module.domain.gradleplugin.GradleCommunityProfilePlugin; import tech.jhipster.lite.module.domain.gradleplugin.GradleCommunityProfilePlugin.GradleCommunityProfilePluginIdBuilder; -import tech.jhipster.lite.module.domain.gradleplugin.GradleCorePlugin; import tech.jhipster.lite.module.domain.gradleplugin.GradleCorePlugin.GradleCorePluginIdBuilder; -import tech.jhipster.lite.module.domain.gradleplugin.JHipsterModuleGradlePlugins; import tech.jhipster.lite.module.domain.gradleplugin.JHipsterModuleGradlePlugins.JHipsterModuleGradlePluginBuilder; import tech.jhipster.lite.module.domain.javabuild.*; import tech.jhipster.lite.module.domain.javabuild.JHipsterModuleMavenBuildExtensions.JHipsterModuleMavenBuildExtensionsBuilder; import tech.jhipster.lite.module.domain.javabuild.MavenBuildExtension.MavenBuildExtensionGroupIdBuilder; -import tech.jhipster.lite.module.domain.javabuildprofile.BuildProfileActivation; +import tech.jhipster.lite.module.domain.javabuildprofile.*; import tech.jhipster.lite.module.domain.javabuildprofile.BuildProfileActivation.BuildProfileActivationBuilder; -import tech.jhipster.lite.module.domain.javabuildprofile.BuildProfileId; -import tech.jhipster.lite.module.domain.javabuildprofile.JHipsterModuleJavaBuildProfiles; import tech.jhipster.lite.module.domain.javabuildprofile.JHipsterModuleJavaBuildProfiles.JHipsterModuleJavaBuildProfilesBuilder; -import tech.jhipster.lite.module.domain.javadependency.DependencyId; -import tech.jhipster.lite.module.domain.javadependency.JHipsterModuleJavaDependencies; +import tech.jhipster.lite.module.domain.javadependency.*; import tech.jhipster.lite.module.domain.javadependency.JHipsterModuleJavaDependencies.JHipsterModuleJavaDependenciesBuilder; -import tech.jhipster.lite.module.domain.javadependency.JavaDependency; import tech.jhipster.lite.module.domain.javadependency.JavaDependency.JavaDependencyGroupIdBuilder; import tech.jhipster.lite.module.domain.javaproperties.*; import tech.jhipster.lite.module.domain.javaproperties.JHipsterModuleSpringFactories.JHipsterModuleSpringFactoriesBuilder; import tech.jhipster.lite.module.domain.javaproperties.JHipsterModuleSpringProperties.JHipsterModuleSpringPropertiesBuilder; -import tech.jhipster.lite.module.domain.mavenplugin.JHipsterModuleMavenPlugins; +import tech.jhipster.lite.module.domain.mavenplugin.*; import tech.jhipster.lite.module.domain.mavenplugin.JHipsterModuleMavenPlugins.JHipsterModuleMavenPluginsBuilder; -import tech.jhipster.lite.module.domain.mavenplugin.MavenPlugin; import tech.jhipster.lite.module.domain.mavenplugin.MavenPlugin.MavenPluginGroupIdBuilder; -import tech.jhipster.lite.module.domain.mavenplugin.MavenPluginExecution; import tech.jhipster.lite.module.domain.mavenplugin.MavenPluginExecution.MavenPluginExecutionGoalsBuilder; -import tech.jhipster.lite.module.domain.packagejson.JHipsterModulePackageJson; +import tech.jhipster.lite.module.domain.packagejson.*; import tech.jhipster.lite.module.domain.packagejson.JHipsterModulePackageJson.JHipsterModulePackageJsonBuilder; -import tech.jhipster.lite.module.domain.packagejson.PackageName; -import tech.jhipster.lite.module.domain.packagejson.ScriptCommand; -import tech.jhipster.lite.module.domain.packagejson.ScriptKey; import tech.jhipster.lite.module.domain.postaction.JHipsterModulePostActions; import tech.jhipster.lite.module.domain.postaction.JHipsterModulePostActions.JHipsterModulePostActionsBuilder; import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties; @@ -526,6 +513,13 @@ JHipsterModuleProperties properties() { return properties; } + public JHipsterModuleBuilder apply(Consumer builderCustomizer) { + Assert.notNull("builderCustomizer", builderCustomizer); + builderCustomizer.accept(this); + + return this; + } + public JHipsterModuleBuilder documentation(DocumentationTitle title, JHipsterSource source) { shortcuts.documentation(title, source); diff --git a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModuleShortcuts.java b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModuleShortcuts.java index 8addcf7a988..6fc7f3416ba 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModuleShortcuts.java +++ b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModuleShortcuts.java @@ -68,14 +68,18 @@ void springTestLogger(String name, LogLevel level) { Assert.notBlank("name", name); Assert.notNull("level", level); - builder.optionalReplacements().in(SPRING_TEST_LOG_FILE).add(JHIPSTER_LOGGER_NEEDLE, logger(name, level)); + builder.optionalReplacements().in(SPRING_TEST_LOG_FILE).add(logConfigurationEntry(name, level)); } void springMainLogger(String name, LogLevel level) { Assert.notBlank("name", name); Assert.notNull("level", level); - builder.optionalReplacements().in(SPRING_MAIN_LOG_FILE).add(JHIPSTER_LOGGER_NEEDLE, logger(name, level)); + builder.optionalReplacements().in(SPRING_MAIN_LOG_FILE).add(logConfigurationEntry(name, level)); + } + + private OptionalReplacer logConfigurationEntry(String name, LogLevel level) { + return new OptionalReplacer(JHIPSTER_LOGGER_NEEDLE, logger(name, level)); } private String logger(String name, LogLevel level) { diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacementsFactory.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacementsFactory.java index 8f7c3550e43..35a31ffff05 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacementsFactory.java +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacementsFactory.java @@ -52,6 +52,12 @@ private JHipsterModuleFileMandatoryReplacementsFactoryBuilder( super(replacements, file); } + public JHipsterModuleFileMandatoryReplacementsFactoryBuilder add(MandatoryReplacer mandatoryReplacer) { + replacements().add(buildReplacer(file(), mandatoryReplacer.replacer(), mandatoryReplacer.updatedValue())); + + return this; + } + @Override protected ContentReplacer buildReplacer(JHipsterProjectFilePath file, ElementReplacer toReplace, String replacement) { return new MandatoryFileReplacer(file, new MandatoryReplacer(toReplace, replacement)); diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacementsFactory.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacementsFactory.java index e5d3e3a8ebc..66df8a99bc9 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacementsFactory.java +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacementsFactory.java @@ -80,6 +80,12 @@ private JHipsterModuleFileOptionalReplacementsFactoryBuilder( super(replacements, file); } + public JHipsterModuleFileOptionalReplacementsFactoryBuilder add(OptionalReplacer mandatoryReplacer) { + replacements().add(buildReplacer(file(), mandatoryReplacer.replacer(), mandatoryReplacer.updatedValue())); + + return this; + } + @Override protected ContentReplacer buildReplacer(JHipsterProjectFilePath file, ElementReplacer toReplace, String replacement) { return new OptionalFileReplacer(file, new OptionalReplacer(toReplace, replacement)); diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleReplacementsFactory.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleReplacementsFactory.java index 59f7957f5ee..ce4abf2b286 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleReplacementsFactory.java +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleReplacementsFactory.java @@ -80,6 +80,14 @@ public Builder add(ElementReplacer elementToReplace, String replacement) { return self(); } + protected ReplacementsBuilder replacements() { + return replacements; + } + + protected JHipsterProjectFilePath file() { + return file; + } + @SuppressWarnings("unchecked") private Builder self() { return (Builder) this; diff --git a/src/main/resources/generator/client/vue/eslint.config.js.mustache b/src/main/resources/generator/client/vue/eslint.config.js.mustache deleted file mode 100644 index bba52802447..00000000000 --- a/src/main/resources/generator/client/vue/eslint.config.js.mustache +++ /dev/null @@ -1,39 +0,0 @@ -import globals from 'globals'; -import typescript from 'typescript-eslint'; -import js from '@eslint/js'; -import vue from 'eslint-plugin-vue'; - -export default typescript.config( - { - languageOptions: { - globals: { - ...globals.node, - }, - }, - }, - { - ignores: ['{{projectBuildDirectory}}/'], - }, - js.configs.recommended, - ...typescript.configs.recommended.map(config => (config.name === 'typescript-eslint/base' ? config : { ...config, files: ['**/*.ts'] })), - ...vue.configs['flat/recommended'], - { - files: ['**/*.vue'], - languageOptions: { - parserOptions: { parser: '@typescript-eslint/parser' }, - globals: { ...globals.browser }, - }, - }, - { - files: ['src/*/webapp/**/*.vue', 'src/*/webapp/**/*.ts'], - languageOptions: { - globals: { ...globals.browser }, - }, - rules: { - quotes: ['error', 'single', { avoidEscape: true }], - '@typescript-eslint/no-explicit-any': 'off', - 'vue/html-self-closing': 'off', - '@typescript-eslint/no-empty-object-type': 'off', - }, - }, -); diff --git a/src/main/resources/generator/client/vue/tsconfig.json b/src/main/resources/generator/client/vue/tsconfig.json deleted file mode 100644 index 6bef65ee0e8..00000000000 --- a/src/main/resources/generator/client/vue/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "@vue/tsconfig/tsconfig.dom.json", - "compilerOptions": { - "allowJs": true, - "sourceMap": true, - "types": ["vite/client", "vitest/globals"], - "baseUrl": ".", - "paths": { - "@/*": ["src/main/webapp/app/*"] - } - }, - "include": ["src/main/webapp/**/*", "src/test/webapp/unit/**/*"] -} diff --git a/src/main/resources/generator/client/vue/vitest.config.ts.mustache b/src/main/resources/generator/client/vue/vitest.config.ts.mustache deleted file mode 100644 index 4f92410710d..00000000000 --- a/src/main/resources/generator/client/vue/vitest.config.ts.mustache +++ /dev/null @@ -1,50 +0,0 @@ -/// - -import tsconfigPaths from 'vite-tsconfig-paths'; -import { defineConfig, configDefaults } from 'vitest/config'; -import vue from '@vitejs/plugin-vue'; - -export default defineConfig({ - plugins: [vue(), tsconfigPaths()], - test: { - reporters: ['verbose', 'vitest-sonar-reporter'], - outputFile: { - 'vitest-sonar-reporter': '{{projectBuildDirectory}}/test-results/TESTS-results-sonar.xml', - }, - globals: true, - logHeapUsage: true, - poolOptions: { - threads: { - minThreads: 1, - maxThreads: 2, - }, - }, - environment: 'jsdom', - cache: false, - include: ['src/test/webapp/unit/**/*.{test,spec}.?(c|m)[jt]s?(x)'], - coverage: { - include: ['src/main/webapp/**/*.ts?(x)'], - exclude: [ - ...configDefaults.coverage.exclude as string[], - 'src/main/webapp/app/main.ts', - 'src/main/webapp/app/injections.ts', - 'src/main/webapp/app/router.ts', - 'src/main/webapp/**/*.component.ts', - ], - provider: 'istanbul', - reportsDirectory: '{{projectBuildDirectory}}/test-results/', - reporter: ['html', 'json-summary', 'text', 'text-summary', 'lcov', 'clover'], - thresholds: { - perFile: true, - autoUpdate: true, - 100: true, - }, - watermarks: { - statements: [100, 100], - branches: [100, 100], - functions: [100, 100], - lines: [100, 100], - }, - }, - }, -}); diff --git a/src/main/resources/generator/typescript/eslint.config.js.mustache b/src/main/resources/generator/typescript/eslint.config.js.mustache index 8fc3802f7cc..1dbd6fc1fcc 100644 --- a/src/main/resources/generator/typescript/eslint.config.js.mustache +++ b/src/main/resources/generator/typescript/eslint.config.js.mustache @@ -1,5 +1,4 @@ import js from '@eslint/js'; -import imports from 'eslint-plugin-import-x'; import globals from 'globals'; import typescript from 'typescript-eslint'; @@ -12,35 +11,10 @@ export default typescript.config( }, }, { - ignores: [ - '{{projectBuildDirectory}}/' - ], + ignores: ['{{projectBuildDirectory}}/'], }, js.configs.recommended, ...typescript.configs.recommended.map(config => (config.name === 'typescript-eslint/base' ? config : { ...config, files: ['**/*.ts'] })), - { - extends: [imports.flatConfigs.recommended, imports.flatConfigs.typescript], - languageOptions: { - // import plugin does not use ecmaVersion and sourceType from languageOptions object - parserOptions: { - ecmaVersion: 2022, - sourceType: 'module', - }, - }, - rules: { - 'import-x/no-unresolved': 'off', - 'import-x/order': [ - 'error', - { - alphabetize: { - order: 'asc', - caseInsensitive: true, - }, - 'newlines-between': 'always', - }, - ], - }, - }, { files: ['src/*/webapp/**/*.ts'], languageOptions: { diff --git a/src/main/resources/generator/typescript/vitest.config.ts.mustache b/src/main/resources/generator/typescript/vitest.config.ts.mustache index 2a0eaee09ce..0dc4d9d3e8e 100644 --- a/src/main/resources/generator/typescript/vitest.config.ts.mustache +++ b/src/main/resources/generator/typescript/vitest.config.ts.mustache @@ -22,7 +22,6 @@ export default defineConfig({ cache: false, include: ['src/test/webapp/unit/**/*.{test,spec}.?(c|m)[jt]s?(x)'], coverage: { - all: true, thresholds: { perFile: true, autoUpdate: true, @@ -32,7 +31,6 @@ export default defineConfig({ exclude: [ ...configDefaults.coverage.exclude as string[], ], - clean: true, provider: 'istanbul', reportsDirectory: '{{projectBuildDirectory}}/test-results/', reporter: ['html', 'json-summary', 'text', 'text-summary', 'lcov', 'clover'], diff --git a/src/test/features/client/vue.feature b/src/test/features/client/vue.feature index 3092bb9150d..ecbfa354129 100644 --- a/src/test/features/client/vue.feature +++ b/src/test/features/client/vue.feature @@ -2,9 +2,10 @@ Feature: Vue.js modules Scenario: Should apply vue core module When I apply modules to default project - | init | - | prettier | - | vue-core | + | init | + | prettier | + | typescript | + | vue-core | Then I should have files in "src/main/webapp/app" | AppVue.vue | diff --git a/src/test/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactoryTest.java index 0c753d47ad6..4aa78c54eff 100644 --- a/src/test/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactoryTest.java +++ b/src/test/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactoryTest.java @@ -24,46 +24,31 @@ void shouldCreateVueModule() { JHipsterModule module = factory.buildVueModule(properties); //@formatter:off - assertThatModuleWithFiles(module, packageJsonFile(), lintStagedConfigFile()) + assertThatModuleWithFiles(module, packageJsonFile(), lintStagedConfigFile(), tsConfigFile(), vitestConfigFile(), eslintConfigFile()) .hasFiles("documentation/vue.md") .hasFile("package.json") + .notContaining(nodeDependency("@tsconfig/recommended")) .containing(nodeDependency("vue")) - .containing(nodeDependency("@typescript-eslint/parser")) .containing(nodeDependency("@vitejs/plugin-vue")) - .containing(nodeDependency("typescript-eslint")) - .containing(nodeDependency("globals")) .containing(nodeDependency("@vue/test-utils")) .containing(nodeDependency("@vue/tsconfig")) - .containing(nodeDependency("@vitest/coverage-istanbul")) - .containing(nodeDependency("eslint")) - .containing(nodeDependency("eslint-config-prettier")) .containing(nodeDependency("eslint-plugin-vue")) .containing(nodeDependency("jsdom")) - .containing(nodeDependency("typescript")) .containing(nodeDependency("vite")) - .containing(nodeDependency("vite-tsconfig-paths")) - .containing(nodeDependency("vitest")) - .containing(nodeDependency("vitest-sonar-reporter")) .containing(nodeDependency("vue-tsc")) .containing(nodeDependency("@types/sinon")) .containing(nodeDependency("sinon")) .containing(nodeDependency("axios")) .containing(nodeDependency("vue-router")) - .containing(nodeDependency("npm-run-all2")) + .containing(nodeDependency("piqure")) .containing(nodeScript("build", "npm-run-all build:*")) .containing(nodeScript("build:tsc", "vue-tsc -p tsconfig.build.json --noEmit")) .containing(nodeScript("build:vite", "vite build --emptyOutDir")) .containing(nodeScript("dev", "npm-run-all --parallel dev:*")) .containing(nodeScript("dev:vite", "vite")) - .containing(nodeScript("watch", "npm-run-all --parallel watch:*")) .containing(nodeScript("watch:tsc", "npm run build:tsc -- --watch")) - .containing(nodeScript("watch:test", "vitest --")) - .containing(nodeDependency("piqure")) - .containing(nodeScript("lint", "eslint .")) .containing(nodeScript("preview", "vite preview")) .containing(nodeScript("start", "vite")) - .containing(nodeScript("test", "npm run watch:test")) - .containing(nodeScript("test:coverage", "vitest run --coverage")) .and() .hasFile(".lintstagedrc.cjs") .containing( @@ -75,7 +60,49 @@ void shouldCreateVueModule() { """ ) .and() - .hasPrefixedFiles("", ".npmrc", "eslint.config.js", "tsconfig.json", "tsconfig.build.json", "vite.config.ts", "vitest.config.ts") + .hasPrefixedFiles("", "eslint.config.js", "tsconfig.build.json", "vite.config.ts", "vitest.config.ts") + .hasFile("tsconfig.json") + .containing("\"extends\": \"@vue/tsconfig/tsconfig.dom.json\"") + .containing("\"allowJs\": true,") + .containing("\"sourceMap\": true,") + .containing("\"types\": [\"vite/client\", ") + .and() + .hasFile("vitest.config.ts") + .containing("import vue from '@vitejs/plugin-vue';") + .containing("plugins: [vue(), tsconfigPaths()],") + .containing("environment: 'jsdom',") + .containing(""" + exclude: [ + ...configDefaults.coverage.exclude as string[], + 'src/main/webapp/app/main.ts', + 'src/main/webapp/app/injections.ts', + 'src/main/webapp/app/router.ts', + 'src/main/webapp/**/*.component.ts', + """ + ) + .and() + .hasFile("eslint.config.js") + .containing("import vue from 'eslint-plugin-vue';") + .containing(""" + ...vue.configs['flat/recommended'], + { + files: ['**/*.vue'], + languageOptions: { + parserOptions: { parser: '@typescript-eslint/parser' }, + globals: { ...globals.browser }, + }, + }, + """ + ) + .containing(""" + rules: { + quotes: ['error', 'single', { avoidEscape: true }], + '@typescript-eslint/no-empty-object-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + 'vue/html-self-closing': 'off', + """ + ) + .and() .hasFiles("src/main/webapp/app/shared/http/infrastructure/secondary/AxiosHttp.ts") .hasFiles("src/main/webapp/index.html") .hasPrefixedFiles("src/main/webapp/app", "env.d.ts", "AppVue.vue", "injections.ts", "router.ts", "main.ts") diff --git a/src/test/java/tech/jhipster/lite/generator/typescript/domain/core/TypescriptModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/typescript/domain/core/TypescriptModuleFactoryTest.java index 0bf06af3607..d73723f1797 100644 --- a/src/test/java/tech/jhipster/lite/generator/typescript/domain/core/TypescriptModuleFactoryTest.java +++ b/src/test/java/tech/jhipster/lite/generator/typescript/domain/core/TypescriptModuleFactoryTest.java @@ -31,7 +31,6 @@ void shouldCreateTypescriptModule() { .containing(nodeDependency("@vitest/coverage-istanbul")) .containing(nodeDependency("eslint")) .containing(nodeDependency("eslint-config-prettier")) - .containing(nodeDependency("eslint-plugin-import-x")) .containing(nodeDependency("globals")) .containing(nodeDependency("typescript-eslint")) .containing(nodeDependency("vite-tsconfig-paths")) @@ -44,6 +43,6 @@ void shouldCreateTypescriptModule() { .containing(nodeScript("watch:tsc", "tsc --noEmit --watch")) .containing(nodeScript("lint", "eslint .")) .and() - .hasPrefixedFiles("", "eslint.config.js", "tsconfig.json"); + .hasPrefixedFiles("", ".npmrc", "eslint.config.js", "tsconfig.json"); } } diff --git a/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/JHipsterModulesAssertions.java b/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/JHipsterModulesAssertions.java index 1b2dbd1d3b8..cb33baf5c79 100644 --- a/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/JHipsterModulesAssertions.java +++ b/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/JHipsterModulesAssertions.java @@ -1,7 +1,7 @@ package tech.jhipster.lite.module.infrastructure.secondary; -import static org.assertj.core.api.Assertions.*; -import static tech.jhipster.lite.TestFileUtils.*; +import static org.assertj.core.api.Assertions.assertThat; +import static tech.jhipster.lite.TestFileUtils.contentNormalizingNewLines; import java.io.IOException; import java.nio.file.*; @@ -60,6 +60,18 @@ public static ModuleFile lintStagedConfigFile() { return file("src/test/resources/projects/init/.lintstagedrc.cjs", ".lintstagedrc.cjs"); } + public static ModuleFile tsConfigFile() { + return file("src/main/resources/generator/typescript/tsconfig.json", "tsconfig.json"); + } + + public static ModuleFile vitestConfigFile() { + return file("src/main/resources/generator/typescript/vitest.config.ts.mustache", "vitest.config.ts"); + } + + public static ModuleFile eslintConfigFile() { + return file("src/main/resources/generator/typescript/eslint.config.js.mustache", "eslint.config.js"); + } + public static ModuleFile emptyLintStagedConfigFile() { return file("src/test/resources/projects/init/.lintstagedrc.empty.cjs", ".lintstagedrc.cjs"); } diff --git a/tests-ci/generate.sh b/tests-ci/generate.sh index c6cc189b5b9..fba0ab04a1c 100755 --- a/tests-ci/generate.sh +++ b/tests-ci/generate.sh @@ -180,6 +180,7 @@ elif [[ $application == 'fullapp' ]]; then frontend_server_plugin applyModules \ + "typescript" \ "vue-core" \ "cypress-component-tests" \ "playwright-e2e" @@ -411,6 +412,7 @@ elif [[ $application == 'vueapp' ]]; then frontend_server_plugin applyModules \ + "typescript" \ "vue-core" \ "vue-pinia" \ "playwright-component-tests" \