Repository: jhipster/jhipster-lite
Pull request #10825 (2024-09-13 20:53:53)

New API for add lintstaged entries + protobuf backwards compatibility check commit hook


Patch:
diff --git a/src/main/java/tech/jhipster/lite/generator/client/angular/core/domain/AngularModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/client/angular/core/domain/AngularModuleFactory.java
index 4d679516b..f1f731efa 100644
--- a/src/main/java/tech/jhipster/lite/generator/client/angular/core/domain/AngularModuleFactory.java
+++ b/src/main/java/tech/jhipster/lite/generator/client/angular/core/domain/AngularModuleFactory.java
@@ -22,11 +22,7 @@ public class AngularModuleFactory {
   public JHipsterModule buildModule(JHipsterModuleProperties properties) {
     //@formatter:off
     return moduleBuilder(properties)
-      .optionalReplacements()
-        .in(path(".lintstagedrc.cjs"))
-          .add(lineBeforeRegex("\\['prettier --write'\\]"), "  '{src/**/,}*.ts': ['eslint --fix', 'prettier --write'],")
-          .and()
-        .and()
+      .preCommitActions(stagedFilesFilter("{src/**/,}*.ts"), preCommitCommands("['eslint --fix', 'prettier --write']"))
       .gitIgnore()
         .comment("Angular")
         .pattern(".angular/")
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 3842b08a4..89cba6851 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
@@ -32,11 +32,7 @@ public class ReactCoreModulesFactory {
   public JHipsterModule buildModule(JHipsterModuleProperties properties) {
     //@formatter:off
     return moduleBuilder(properties)
-      .optionalReplacements()
-        .in(path(".lintstagedrc.cjs"))
-          .add(lineBeforeRegex("\\['prettier --write'\\]"), "  '{src/**/,}*.{ts,tsx}': ['eslint --fix', 'prettier --write'],")
-          .and()
-        .and()
+      .preCommitActions(stagedFilesFilter("{src/**/,}*.{ts,tsx}"), preCommitCommands("['eslint --fix', 'prettier --write']"))
       .packageJson()
         .type(MODULE)
         .addDevDependency(packageName("@testing-library/dom"), REACT)
diff --git a/src/main/java/tech/jhipster/lite/generator/client/svelte/core/domain/SvelteModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/client/svelte/core/domain/SvelteModuleFactory.java
index 9cf724770..481555f28 100644
--- a/src/main/java/tech/jhipster/lite/generator/client/svelte/core/domain/SvelteModuleFactory.java
+++ b/src/main/java/tech/jhipster/lite/generator/client/svelte/core/domain/SvelteModuleFactory.java
@@ -29,11 +29,7 @@ public class SvelteModuleFactory {
 
     //@formatter:off
     return moduleBuilder(properties)
-      .optionalReplacements()
-        .in(path(".lintstagedrc.cjs"))
-        .add(lineBeforeRegex("\\['prettier --write'\\]"), "  '{src/**/,}*.ts': ['eslint --fix', 'prettier --write'],")
-        .and()
-      .and()
+      .preCommitActions(stagedFilesFilter("{src/**/,}*.ts"), preCommitCommands("['eslint --fix', 'prettier --write']"))
       .gitIgnore()
         .comment("Svelte")
         .pattern(".svelte-kit/")
@@ -94,7 +90,6 @@ public class SvelteModuleFactory {
           .addFile(".eslintignore")
           .addFile(".npmrc")
           .and()
-        .move(path(".lintstagedrc.js"), to(".lintstagedrc.cjs"))
         .batch(SOURCE, to("."))
           .addTemplate("svelte.config.js")
           .addTemplate("vitest.config.ts")
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 fe81ff5b0..12d1baed9 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
@@ -38,11 +38,7 @@ public class VueModulesFactory {
   public JHipsterModule buildVueModule(JHipsterModuleProperties properties) {
     //@formatter:off
     return moduleBuilder(properties)
-      .optionalReplacements()
-        .in(path(".lintstagedrc.cjs"))
-          .add(lineBeforeRegex("\\['prettier --write'\\]"), "  '{src/**/,}*.{ts,vue}': ['eslint --fix', 'prettier --write'],")
-          .and()
-        .and()
+      .preCommitActions(stagedFilesFilter("{src/**/,}*.{ts,vue}"), preCommitCommands("['eslint --fix', 'prettier --write']"))
       .documentation(documentationTitle("Vue"), DOCUMENTATION_SOURCE.file("vue.md"))
       .packageJson()
         .type(MODULE)
diff --git a/src/main/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactory.java
index 99cea021f..d8898df00 100644
--- a/src/main/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactory.java
+++ b/src/main/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactory.java
@@ -3,38 +3,17 @@ package tech.jhipster.lite.generator.prettier.domain;
 import static tech.jhipster.lite.module.domain.JHipsterModule.*;
 import static tech.jhipster.lite.module.domain.packagejson.VersionSource.COMMON;
 
-import java.util.regex.Pattern;
 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.ElementReplacer;
-import tech.jhipster.lite.module.domain.replacement.RegexReplacer;
 
 public class PrettierModuleFactory {
 
   private static final JHipsterSource SOURCE = from("prettier");
   private static final JHipsterDestination DESTINATION = to(".");
 
-  private static final Pattern MODULE_EXPORT = Pattern.compile("module.exports = \\{");
-  private static final Pattern DEFAULT_ES_LINT = Pattern.compile("'\\*': \\[], //default configuration, replace with your own");
-
-  private static final ElementReplacer EXISTING_ESLINT_CONFIGURATION = new RegexReplacer(
-    (contentBeforeReplacement, replacement) -> MODULE_EXPORT.matcher(contentBeforeReplacement).find(),
-    MODULE_EXPORT
-  );
-
-  private static final ElementReplacer DEFAULT_ES_LINT_CONFIGURATION = new RegexReplacer(
-    (contentBeforeReplacement, replacement) -> DEFAULT_ES_LINT.matcher(contentBeforeReplacement).find(),
-    DEFAULT_ES_LINT
-  );
-
   public JHipsterModule buildModule(JHipsterModuleProperties properties) {
-    String esLintReplacement =
-      "module.exports = \\{" +
-      LINE_BREAK +
-      properties.indentation().times(1) +
-      "'*.{md,json,yml,html,css,scss,java,xml,feature}': ['prettier --write'],";
     //@formatter:off
     return moduleBuilder(properties)
       .context()
@@ -56,12 +35,7 @@ public class PrettierModuleFactory {
         .addScript(scriptKey("prettier:check"), scriptCommand("prettier --check ."))
         .addScript(scriptKey("prettier:format"), scriptCommand("prettier --write ."))
         .and()
-      .optionalReplacements()
-        .in(path(DESTINATION + "lintstagedrc.cjs"))
-          .add(DEFAULT_ES_LINT_CONFIGURATION, "")
-          .add(EXISTING_ESLINT_CONFIGURATION, esLintReplacement)
-      .and()
-      .and()
+      .preCommitActions(stagedFilesFilter("*.{md,json,yml,html,css,scss,java,xml,feature}"), preCommitCommands("['prettier --write']"))
       .build();
     //@formatter:on
   }
diff --git a/src/main/java/tech/jhipster/lite/generator/server/javatool/protobuf/domain/ProtobufModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/server/javatool/protobuf/domain/ProtobufModuleFactory.java
index 6d7c1025b..33ef589e0 100644
--- a/src/main/java/tech/jhipster/lite/generator/server/javatool/protobuf/domain/ProtobufModuleFactory.java
+++ b/src/main/java/tech/jhipster/lite/generator/server/javatool/protobuf/domain/ProtobufModuleFactory.java
@@ -110,6 +110,7 @@ public class ProtobufModuleFactory {
         .pluginManagement(protoBackwardsCompatibilityMavenPluginManagement())
         .plugin(protoBackwardsCompatibilityMavenPluginBuilder().build())
         .and()
+      .preCommitActions(stagedFilesFilter("*.proto"), preCommitCommands("() => ['mvn proto-backwards-compatibility:backwards-compatibility-check', 'git add *proto.lock']"))
       .build();
     //@formatter:on
   }
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 768f5f7ae..28ae498c6 100644
--- a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java
+++ b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java
@@ -358,6 +358,14 @@ public final class JHipsterModule {
     return new PackageName(packageName);
   }
 
+  public static StagedFilesFilter stagedFilesFilter(String filesFilter) {
+    return new StagedFilesFilter(filesFilter);
+  }
+
+  public static PreCommitCommands preCommitCommands(String commands) {
+    return new PreCommitCommands(commands);
+  }
+
   public static GradleCorePluginIdBuilder gradleCorePlugin() {
     return GradleCorePlugin.builder();
   }
@@ -530,6 +538,12 @@ public final class JHipsterModule {
       return this;
     }
 
+    public JHipsterModuleBuilder preCommitActions(StagedFilesFilter stagedFilesFilter, PreCommitCommands preCommitCommands) {
+      shortcuts.preCommitActions(stagedFilesFilter, preCommitCommands);
+
+      return this;
+    }
+
     public JHipsterModuleStartupCommandsBuilder startupCommands() {
       return startupCommands;
     }
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 73aa4a839..8addcf7a9 100644
--- a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModuleShortcuts.java
+++ b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModuleShortcuts.java
@@ -2,9 +2,9 @@ package tech.jhipster.lite.module.domain;
 
 import static tech.jhipster.lite.module.domain.JHipsterModule.*;
 
+import java.util.regex.Pattern;
 import tech.jhipster.lite.module.domain.file.JHipsterSource;
-import tech.jhipster.lite.module.domain.replacement.TextNeedleAfterReplacer;
-import tech.jhipster.lite.module.domain.replacement.TextNeedleBeforeReplacer;
+import tech.jhipster.lite.module.domain.replacement.*;
 import tech.jhipster.lite.shared.error.domain.Assert;
 
 final class JHipsterModuleShortcuts {
@@ -21,6 +21,19 @@ final class JHipsterModuleShortcuts {
   private static final JHipsterProjectFilePath SPRING_TEST_LOG_FILE = path("src/test/resources/logback.xml");
   private static final TextNeedleBeforeReplacer JHIPSTER_LOGGER_NEEDLE = lineBeforeText("<!-- jhipster-needle-logback-add-log -->");
 
+  private static final Pattern MODULE_EXPORT = Pattern.compile("module.exports = \\{");
+  private static final Pattern DEFAULT_ES_LINT = Pattern.compile("\\s*'\\*': \\[], //default configuration, replace with your own");
+
+  private static final ElementReplacer EXISTING_ESLINT_CONFIGURATION = new RegexReplacer(
+    (contentBeforeReplacement, replacement) -> MODULE_EXPORT.matcher(contentBeforeReplacement).find(),
+    MODULE_EXPORT
+  );
+
+  private static final ElementReplacer DEFAULT_ES_LINT_CONFIGURATION = new RegexReplacer(
+    (contentBeforeReplacement, replacement) -> DEFAULT_ES_LINT.matcher(contentBeforeReplacement).find(),
+    DEFAULT_ES_LINT
+  );
+
   private final JHipsterModuleBuilder builder;
 
   JHipsterModuleShortcuts(JHipsterModuleBuilder builder) {
@@ -88,4 +101,21 @@ final class JHipsterModuleShortcuts {
       )
       .add(lineBeforeText("public @interface"), "@ExtendWith(" + extensionClass + ".class)");
   }
+
+  public void preCommitActions(StagedFilesFilter stagedFilesFilter, PreCommitCommands preCommitCommands) {
+    Assert.notNull("stagedFilesFilter", stagedFilesFilter);
+    Assert.notNull("preCommitCommands", preCommitCommands);
+
+    String esLintReplacement =
+      "module.exports = \\{" +
+      LINE_BREAK +
+      builder.properties().indentation().times(1) +
+      "'%s': %s,".formatted(stagedFilesFilter.get(), preCommitCommands.get());
+
+    builder
+      .optionalReplacements()
+      .in(path(".lintstagedrc.cjs"))
+      .add(DEFAULT_ES_LINT_CONFIGURATION, "")
+      .add(EXISTING_ESLINT_CONFIGURATION, esLintReplacement);
+  }
 }
diff --git a/src/main/java/tech/jhipster/lite/module/domain/PreCommitCommands.java b/src/main/java/tech/jhipster/lite/module/domain/PreCommitCommands.java
new file mode 100644
index 000000000..e51b627f9
--- /dev/null
+++ b/src/main/java/tech/jhipster/lite/module/domain/PreCommitCommands.java
@@ -0,0 +1,13 @@
+package tech.jhipster.lite.module.domain;
+
+import tech.jhipster.lite.shared.error.domain.Assert;
+
+public record PreCommitCommands(String commands) {
+  public PreCommitCommands {
+    Assert.notBlank("commands", commands);
+  }
+
+  public String get() {
+    return commands;
+  }
+}
diff --git a/src/main/java/tech/jhipster/lite/module/domain/StagedFilesFilter.java b/src/main/java/tech/jhipster/lite/module/domain/StagedFilesFilter.java
new file mode 100644
index 000000000..ad1fb2399
--- /dev/null
+++ b/src/main/java/tech/jhipster/lite/module/domain/StagedFilesFilter.java
@@ -0,0 +1,13 @@
+package tech.jhipster.lite.module.domain;
+
+import tech.jhipster.lite.shared.error.domain.Assert;
+
+public record StagedFilesFilter(String filter) {
+  public StagedFilesFilter {
+    Assert.notBlank("filter", filter);
+  }
+
+  public String get() {
+    return filter();
+  }
+}


Test patch:
diff --git a/src/test/java/tech/jhipster/lite/generator/client/svelte/core/domain/SvelteModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/client/svelte/core/domain/SvelteModuleFactoryTest.java
index 18ffe4ef4..1be370445 100644
--- a/src/test/java/tech/jhipster/lite/generator/client/svelte/core/domain/SvelteModuleFactoryTest.java
+++ b/src/test/java/tech/jhipster/lite/generator/client/svelte/core/domain/SvelteModuleFactoryTest.java
@@ -21,7 +21,7 @@ class SvelteModuleFactoryTest {
     JHipsterModule module = factory.buildSvelteModule(properties);
 
     // @formatter:off
-    assertThatModuleWithFiles(module, packageJsonFile(), lintstagedFile())
+    assertThatModuleWithFiles(module, packageJsonFile(), lintStagedConfigFile())
       .hasFile(".gitignore")
         .containing("""
           # Svelte
@@ -72,13 +72,7 @@ class SvelteModuleFactoryTest {
       .hasPrefixedFiles("src/test/webapp/unit/common/primary/app", "App.spec.ts")
       .hasPrefixedFiles("src/main/webapp/app/common/primary/app", "App.svelte")
       .hasPrefixedFiles("src/main/webapp/assets", "JHipster-Lite-neon-orange.png")
-      .hasPrefixedFiles("src/main/webapp/assets", "svelte-logo.png")
-      .hasFiles(".lintstagedrc.cjs")
-      .doNotHaveFiles(".lintstagedrc.js");
+      .hasPrefixedFiles("src/main/webapp/assets", "svelte-logo.png");
     // @formatter:on
   }
-
-  private ModuleFile lintstagedFile() {
-    return file("src/test/resources/projects/files/.lintstagedrc.js", ".lintstagedrc.js");
-  }
 }
diff --git a/src/test/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactoryTest.java
index 03e9e438b..5c9496a5e 100644
--- a/src/test/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactoryTest.java
+++ b/src/test/java/tech/jhipster/lite/generator/prettier/domain/PrettierModuleFactoryTest.java
@@ -26,13 +26,20 @@ class PrettierModuleFactoryTest {
 
     JHipsterModule module = factory.buildModule(properties);
 
-    assertThatModuleWithFiles(module, packageJsonFile(), withoutPrettierLintStagedConfigFile())
+    assertThatModuleWithFiles(module, packageJsonFile(), lintStagedConfigFileWithoutPrettier())
       .hasFiles(".prettierignore")
       .hasFile(".lintstagedrc.cjs")
-      .containing("'*.{md,json,yml,html,css,scss,java,xml,feature}': ['prettier --write'],")
+      .containing(
+        """
+        module.exports = {
+          '*.{md,json,yml,html,css,scss,java,xml,feature}': ['prettier --write'],
+          '*.pug': ['eslint --fix', 'prettier --write'],
+        };
+        """
+      )
       .and()
       .hasFile(".prettierrc")
-      .containing("tabWidth: 4")
+      .containing("tabWidth: 2")
       .containing("endOfLine: 'crlf'")
       .containing("@prettier/plugin-xml")
       .containing("prettier-plugin-gherkin")
@@ -58,15 +65,20 @@ class PrettierModuleFactoryTest {
 
     assertThatModuleWithFiles(module, packageJsonFile(), emptyLintStagedConfigFile())
       .hasFile(".lintstagedrc.cjs")
-      .containing("'*.{md,json,yml,html,css,scss,java,xml,feature}': ['prettier --write']")
-      .notContaining("default configuration, replace with your own");
+      .containing(
+        """
+        module.exports = {
+          '*.{md,json,yml,html,css,scss,java,xml,feature}': ['prettier --write'],
+        };
+        """
+      );
   }
 
   private JHipsterModuleProperties properties(String folder) {
     return JHipsterModulesFixture.propertiesBuilder(folder)
       .projectBaseName("testProject")
       .put("projectName", "Test Project")
-      .put("indentSize", 4)
+      .put("indentSize", 2)
       .put("endOfLine", "crlf")
       .build();
   }
diff --git a/src/test/java/tech/jhipster/lite/generator/server/javatool/protobuf/domain/ProtobufModuleFactoryTest.java b/src/test/java/tech/jhipster/lite/generator/server/javatool/protobuf/domain/ProtobufModuleFactoryTest.java
index 2a719c08a..1a98c55d3 100644
--- a/src/test/java/tech/jhipster/lite/generator/server/javatool/protobuf/domain/ProtobufModuleFactoryTest.java
+++ b/src/test/java/tech/jhipster/lite/generator/server/javatool/protobuf/domain/ProtobufModuleFactoryTest.java
@@ -142,7 +142,17 @@ class ProtobufModuleFactoryTest {
 
       JHipsterModule module = factory.buildProtobufBackwardsCompatibilityCheckModule(properties);
 
-      assertThatModuleWithFiles(module, pomFile())
+      assertThatModuleWithFiles(module, pomFile(), lintStagedConfigFile())
+        .hasFile(".lintstagedrc.cjs")
+        .containing(
+          """
+          module.exports = {
+            '*.proto': () => ['mvn proto-backwards-compatibility:backwards-compatibility-check', 'git add *proto.lock'],
+            '*.{md,json,yml,html,css,scss,java,xml,feature}': ['prettier --write'],
+          };
+          """
+        )
+        .and()
         .hasFile("pom.xml")
         .containing(
           """
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 a2ef1ce84..1b2dbd1d3 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
@@ -64,7 +64,7 @@ public final class JHipsterModulesAssertions {
     return file("src/test/resources/projects/init/.lintstagedrc.empty.cjs", ".lintstagedrc.cjs");
   }
 
-  public static ModuleFile withoutPrettierLintStagedConfigFile() {
+  public static ModuleFile lintStagedConfigFileWithoutPrettier() {
     return file("src/test/resources/projects/init/.lintstagedrc.withoutPrettier.cjs", ".lintstagedrc.cjs");
   }