Skip to content

Commit 78bbd5d

Browse files
vaadin-bottltv
andauthored
fix: install hilla-generator dependencies if Hilla is available (#23012) (#23029)
Adds hilla-generator-* dependencies to package.json when Hilla is available via EndpointRequestUtil.isHillaAvailable(), not only when Hilla is used (FrontendUtils.isHillaUsed(...)). Fixes: vaadin/hilla#4283 Co-authored-by: Tomi Virtanen <tltv@vaadin.com>
1 parent 61dd0c1 commit 78bbd5d

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

flow-server/src/main/java/com/vaadin/flow/server/frontend/NodeUpdater.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import com.vaadin.flow.internal.JacksonUtils;
4242
import com.vaadin.flow.internal.JsonDecodingException;
4343
import com.vaadin.flow.internal.StringUtil;
44+
import com.vaadin.flow.internal.hilla.EndpointRequestUtil;
4445
import com.vaadin.flow.server.Constants;
4546
import com.vaadin.flow.server.frontend.scanner.ClassFinder;
4647
import com.vaadin.flow.server.frontend.scanner.FrontendDependencies;
@@ -362,6 +363,14 @@ boolean hasPackageJson(String id) {
362363
+ "dependencies/" + id + "/package.json") != null;
363364
}
364365

366+
Map<String, String> readDependenciesIfAvailable(String id,
367+
String packageJsonKey, String contains) {
368+
return readDependenciesIfAvailable(id, packageJsonKey).entrySet()
369+
.stream().filter(entry -> entry.getKey().contains(contains))
370+
.collect(Collectors.toMap(Map.Entry::getKey,
371+
Map.Entry::getValue));
372+
}
373+
365374
Map<String, String> readDependenciesIfAvailable(String id,
366375
String packageJsonKey) {
367376
if (hasPackageJson(id)) {
@@ -643,6 +652,20 @@ private void putHillaComponentsDependencies(
643652
dependencies.putAll(readDependenciesIfAvailable(
644653
"hilla/components/lit", packageJsonKey));
645654
}
655+
} else if (EndpointRequestUtil.isHillaAvailable()) {
656+
// Add dependencies for hilla-generator in case Hilla is available
657+
// in the classpath. This ensures that 'generate' Maven/Gradle goal
658+
// has required dependencies installed even when Hilla views are not
659+
// used.
660+
if (options.isReactEnabled()) {
661+
dependencies.putAll(
662+
readDependenciesIfAvailable("hilla/components/react",
663+
packageJsonKey, "@vaadin/hilla-generator-"));
664+
} else {
665+
dependencies.putAll(
666+
readDependenciesIfAvailable("hilla/components/lit",
667+
packageJsonKey, "@vaadin/hilla-generator-"));
668+
}
646669
}
647670
}
648671

flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdaterTest.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
import com.vaadin.experimental.FeatureFlags;
4343
import com.vaadin.flow.internal.JacksonUtils;
44+
import com.vaadin.flow.internal.hilla.EndpointRequestUtil;
4445
import com.vaadin.flow.server.Constants;
4546
import com.vaadin.flow.server.frontend.scanner.ClassFinder;
4647
import com.vaadin.flow.server.frontend.scanner.FrontendDependencies;
@@ -832,6 +833,56 @@ Logger log() {
832833
Mockito.verifyNoInteractions(log);
833834
}
834835

836+
@Test
837+
public void getDefaultDependencies_hillaAvailableButNotUsed_addsGeneratorDependencies() {
838+
boolean reactEnabled = options.isReactEnabled();
839+
try (MockedStatic<FrontendUtils> frontendUtilsMock = Mockito
840+
.mockStatic(FrontendUtils.class);
841+
MockedStatic<EndpointRequestUtil> endpointUtilMock = Mockito
842+
.mockStatic(EndpointRequestUtil.class)) {
843+
844+
// Hilla is available in classpath but not used
845+
frontendUtilsMock.when(
846+
() -> FrontendUtils.isHillaUsed(Mockito.any(File.class),
847+
Mockito.any(ClassFinder.class)))
848+
.thenReturn(false);
849+
endpointUtilMock.when(EndpointRequestUtil::isHillaAvailable)
850+
.thenReturn(true);
851+
frontendUtilsMock
852+
.when(() -> FrontendUtils
853+
.isReactRouterRequired(Mockito.any(File.class)))
854+
.thenReturn(true);
855+
856+
// Create a spy to mock the readDependenciesIfAvailable method
857+
NodeUpdater spyNodeUpdater = Mockito.spy(nodeUpdater);
858+
Map<String, String> mockGeneratorDeps = Map
859+
.of("@vaadin/hilla-generator-core", "2.0.0");
860+
Mockito.doReturn(mockGeneratorDeps).when(spyNodeUpdater)
861+
.readDependenciesIfAvailable(Mockito.anyString(),
862+
Mockito.eq("dependencies"),
863+
Mockito.eq("@vaadin/hilla-generator-"));
864+
865+
// Test with React enabled
866+
options.withReact(true);
867+
Map<String, String> defaultDeps = spyNodeUpdater
868+
.getDefaultDependencies();
869+
Assert.assertTrue(
870+
"React generator dependency should be added when Hilla is available",
871+
defaultDeps.keySet().stream().anyMatch(
872+
key -> key.contains("@vaadin/hilla-generator-")));
873+
874+
// Test with React disabled
875+
options.withReact(false);
876+
defaultDeps = spyNodeUpdater.getDefaultDependencies();
877+
Assert.assertTrue(
878+
"Lit generator dependency should be added when Hilla is available",
879+
defaultDeps.keySet().stream().anyMatch(
880+
key -> key.contains("@vaadin/hilla-generator-")));
881+
} finally {
882+
options.withReact(reactEnabled);
883+
}
884+
}
885+
835886
private String getPolymerVersion(JsonNode object) {
836887
JsonNode deps = object.get("dependencies");
837888
return deps.get("@polymer/polymer").textValue();

0 commit comments

Comments
 (0)