Skip to content

Commit e771943

Browse files
feat: expose application properties via Options for TypeScriptBootstrapModifier consumers (#24073) (CP: 25.1) (#24248)
This PR cherry-picks changes from the original PR #24073 to branch 25.1. --- #### Original PR description > `TypeScriptBootstrapModifier` implementations (e.g., Copilot) need access > to application properties to conditionally modify bootstrap TypeScript. > Currently, the Copilot script is injected in dev mode regardless of > whether Copilot is enabled in the project configuration. > > Add `withApplicationConfiguration` to `Options` and property accessor > methods (`getApplicationStringProperty`, `getApplicationBooleanProperty`) > that return `Optional.empty()` when configuration is unavailable (build > time). Wire `ApplicationConfiguration` from `DevModeInitializer`. > > Fixes #24055 Co-authored-by: Marco Collovati <marco@vaadin.com>
1 parent 3bf9f2d commit e771943

3 files changed

Lines changed: 137 additions & 0 deletions

File tree

flow-build-tools/src/main/java/com/vaadin/flow/server/frontend/Options.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.ArrayList;
2222
import java.util.List;
2323
import java.util.Objects;
24+
import java.util.Optional;
2425
import java.util.Set;
2526

2627
import org.slf4j.LoggerFactory;
@@ -34,6 +35,7 @@
3435
import com.vaadin.flow.server.frontend.installer.NodeInstaller;
3536
import com.vaadin.flow.server.frontend.scanner.ClassFinder;
3637
import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner;
38+
import com.vaadin.flow.server.startup.ApplicationConfiguration;
3739

3840
/**
3941
* Build a <code>NodeExecutor</code> instance.
@@ -164,6 +166,8 @@ public class Options implements Serializable {
164166

165167
private boolean commercialBannerEnabled = false;
166168

169+
private ApplicationConfiguration applicationConfiguration;
170+
167171
/**
168172
* Creates a new instance.
169173
*
@@ -193,6 +197,21 @@ public Options(Lookup lookup, ClassFinder classFinder, File npmFolder) {
193197
this.npmFolder = npmFolder;
194198
}
195199

200+
/**
201+
* Sets the application configuration for the current options and returns
202+
* the updated options instance.
203+
*
204+
* @param applicationConfiguration
205+
* the application configuration to be applied
206+
* @return the updated {@code Options} instance with the specified
207+
* application configuration
208+
*/
209+
public Options withApplicationConfiguration(
210+
ApplicationConfiguration applicationConfiguration) {
211+
this.applicationConfiguration = applicationConfiguration;
212+
return this;
213+
}
214+
196215
/**
197216
* Sets the directory containing the project's frontend files
198217
*
@@ -1140,4 +1159,42 @@ public Options withMetaInfResourcesDirectory(File resourcesDirectory) {
11401159
public File getMetaInfResourcesDirectory() {
11411160
return resourcesDirectory;
11421161
}
1162+
1163+
/**
1164+
* Retrieves the value of a string application property.
1165+
* <p>
1166+
* Returns an empty {@code Optional} if the application configuration is not
1167+
* available (e.g., at build time). When configuration is available, returns
1168+
* the property value or the given default.
1169+
*
1170+
* @param name
1171+
* the name of the property to retrieve
1172+
* @param defaultValue
1173+
* the value to return if the property is not set
1174+
* @return the property value, or empty if configuration is unavailable
1175+
*/
1176+
public Optional<String> getApplicationStringProperty(String name,
1177+
String defaultValue) {
1178+
return Optional.ofNullable(applicationConfiguration)
1179+
.map(app -> app.getStringProperty(name, defaultValue));
1180+
}
1181+
1182+
/**
1183+
* Retrieves the value of a boolean application property.
1184+
* <p>
1185+
* Returns an empty {@code Optional} if the application configuration is not
1186+
* available (e.g., at build time). When configuration is available, returns
1187+
* the property value or the given default.
1188+
*
1189+
* @param name
1190+
* the name of the property to retrieve
1191+
* @param defaultValue
1192+
* the value to return if the property is not set
1193+
* @return the property value, or empty if configuration is unavailable
1194+
*/
1195+
public Optional<Boolean> getApplicationBooleanProperty(String name,
1196+
boolean defaultValue) {
1197+
return Optional.ofNullable(applicationConfiguration)
1198+
.map(app -> app.getBooleanProperty(name, defaultValue));
1199+
}
11431200
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2000-2026 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.vaadin.flow.server.frontend;
17+
18+
import java.io.File;
19+
import java.util.Optional;
20+
21+
import org.junit.jupiter.api.Test;
22+
import org.mockito.Mockito;
23+
24+
import com.vaadin.flow.server.startup.ApplicationConfiguration;
25+
import com.vaadin.tests.util.MockOptions;
26+
27+
import static org.junit.jupiter.api.Assertions.assertEquals;
28+
import static org.junit.jupiter.api.Assertions.assertTrue;
29+
30+
class OptionsApplicationPropertiesTest {
31+
32+
@Test
33+
void getApplicationBooleanProperty_configAvailable_returnsPropertyValue() {
34+
ApplicationConfiguration config = Mockito
35+
.mock(ApplicationConfiguration.class);
36+
Mockito.when(config.getBooleanProperty("test.prop", false))
37+
.thenReturn(true);
38+
39+
Options options = new MockOptions(new File("."))
40+
.withApplicationConfiguration(config);
41+
42+
Optional<Boolean> result = options
43+
.getApplicationBooleanProperty("test.prop", false);
44+
assertEquals(Optional.of(true), result);
45+
}
46+
47+
@Test
48+
void getApplicationBooleanProperty_noConfig_returnsEmpty() {
49+
Options options = new MockOptions(new File("."));
50+
51+
Optional<Boolean> result = options
52+
.getApplicationBooleanProperty("test.prop", true);
53+
assertTrue(result.isEmpty());
54+
}
55+
56+
@Test
57+
void getApplicationStringProperty_configAvailable_returnsPropertyValue() {
58+
ApplicationConfiguration config = Mockito
59+
.mock(ApplicationConfiguration.class);
60+
Mockito.when(config.getStringProperty("test.prop", "default"))
61+
.thenReturn("custom");
62+
63+
Options options = new MockOptions(new File("."))
64+
.withApplicationConfiguration(config);
65+
66+
Optional<String> result = options
67+
.getApplicationStringProperty("test.prop", "default");
68+
assertEquals(Optional.of("custom"), result);
69+
}
70+
71+
@Test
72+
void getApplicationStringProperty_noConfig_returnsEmpty() {
73+
Options options = new MockOptions(new File("."));
74+
75+
Optional<String> result = options
76+
.getApplicationStringProperty("test.prop", "default");
77+
assertTrue(result.isEmpty());
78+
}
79+
}

vaadin-dev-server/src/main/java/com/vaadin/base/devserver/startup/DevModeInitializer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ public static DevModeHandler initDevModeHandler(Set<Class<?>> classes,
221221
ClassFinder.class);
222222
Lookup lookup = Lookup.compose(lookupForClassFinder, lookupFromContext);
223223
Options options = new Options(lookup, baseDir)
224+
.withApplicationConfiguration(config)
224225
.withFrontendDirectory(frontendFolder)
225226
.withFrontendGeneratedFolder(
226227
new File(frontendFolder + FrontendUtils.GENERATED))

0 commit comments

Comments
 (0)