Skip to content

Commit b83923e

Browse files
authored
Merge branch 'main' into feature/new-auto-grid-attribute-hidden-columns
2 parents e89d857 + bf9054d commit b83923e

File tree

10 files changed

+84
-55
lines changed

10 files changed

+84
-55
lines changed

packages/java/endpoint/src/main/java/com/vaadin/hilla/route/ClientRouteRegistry.java

+28-16
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
@Component
4343
public class ClientRouteRegistry implements Serializable {
4444

45+
public static final String FILE_ROUTES_JSON_NAME = "file-routes.json";
46+
public static final String FILE_ROUTES_JSON_PROD_PATH = "/META-INF/VAADIN/"
47+
+ FILE_ROUTES_JSON_NAME;
48+
4549
/**
4650
* A map of registered routes and their corresponding client view
4751
* configurations with ordered insertion.
@@ -121,51 +125,59 @@ private String removeTrailingSlash(String path) {
121125
}
122126

123127
/**
124-
* Registers client routes from views.json file generated by the
125-
* file-router's Vite plugin. The views.json file is expected to be in the
126-
* frontend/generated folder in dev mode and in the META-INF/VAADIN folder
127-
* in production mode.
128+
* Registers client routes from file-routes.json file generated by the
129+
* file-router's Vite plugin. The file-routes.json file is expected to be in
130+
* the frontend/generated folder in dev mode and in the META-INF/VAADIN
131+
* folder in production mode.
128132
*
129133
* @param deploymentConfiguration
130134
* the deployment configuration
135+
*
136+
* @return {@code true} if the client routes were successfully registered,
137+
* {@code false} otherwise
131138
*/
132-
public void registerClientRoutes(
139+
public boolean registerClientRoutes(
133140
DeploymentConfiguration deploymentConfiguration) {
134141
var viewsJsonAsResource = getViewsJsonAsResource(
135142
deploymentConfiguration);
136-
if (viewsJsonAsResource == null || !Paths
137-
.get(viewsJsonAsResource.getPath()).toFile().exists()) {
143+
if (viewsJsonAsResource == null) {
138144
LOGGER.debug(
139-
"No 'views.json' found either in the frontend/generated "
140-
+ "folder or in the META-INF/VAADIN folder. Skipping client "
141-
+ "route registration.");
142-
return;
145+
"No {} found under {} directory. Skipping client route registration.",
146+
FILE_ROUTES_JSON_NAME,
147+
deploymentConfiguration.isProductionMode()
148+
? "'META-INF/VAADIN'"
149+
: "'frontend/generated'");
150+
return false;
143151
}
144152
try (var source = viewsJsonAsResource.openStream()) {
145153
if (source != null) {
146154
clearRoutes();
147155
registerAndRecurseChildren("",
148156
mapper.readValue(source, new TypeReference<>() {
149157
}));
158+
return true;
150159
}
160+
return false;
151161
} catch (IOException e) {
152-
LOGGER.warn("Failed load client views from {}",
162+
LOGGER.warn("Failed load {} from {}", FILE_ROUTES_JSON_NAME,
153163
viewsJsonAsResource.getPath(), e);
164+
return false;
154165
}
155166
}
156167

157168
private URL getViewsJsonAsResource(
158169
DeploymentConfiguration deploymentConfiguration) {
159170
var isProductionMode = deploymentConfiguration.isProductionMode();
160171
if (isProductionMode) {
161-
return getClass().getResource("/META-INF/VAADIN/views.json");
172+
return getClass().getResource(FILE_ROUTES_JSON_PROD_PATH);
162173
}
163174
try {
164175
return deploymentConfiguration.getFrontendFolder().toPath()
165-
.resolve("generated").resolve("views.json").toUri().toURL();
176+
.resolve("generated").resolve(FILE_ROUTES_JSON_NAME).toUri()
177+
.toURL();
166178
} catch (MalformedURLException e) {
167-
LOGGER.warn("Failed to find views.json under frontend/generated",
168-
e);
179+
LOGGER.warn("Failed to find {} under frontend/generated",
180+
FILE_ROUTES_JSON_NAME, e);
169181
throw new RuntimeException(e);
170182
}
171183
}

packages/java/endpoint/src/main/java/com/vaadin/hilla/route/RouteUnifyingIndexHtmlRequestListener.java

+21-12
Original file line numberDiff line numberDiff line change
@@ -78,22 +78,27 @@ public void modifyIndexHtmlResponse(IndexHtmlResponse response) {
7878
collectServerViews(availableViews);
7979

8080
if (availableViews.isEmpty()) {
81+
LOGGER.debug(
82+
"No server-side nor client-side views found, skipping response modification.");
8183
return;
8284
}
8385
try {
84-
final String viewsJson = mapper.writeValueAsString(availableViews);
85-
final String script = SCRIPT_STRING.formatted(viewsJson);
86+
final String fileRoutesJson = mapper
87+
.writeValueAsString(availableViews);
88+
final String script = SCRIPT_STRING.formatted(fileRoutesJson);
8689
response.getDocument().head().appendElement("script")
8790
.appendChild(new DataNode(script));
8891
} catch (IOException e) {
89-
LOGGER.error("Failed to write server views to index response", e);
92+
LOGGER.error(
93+
"Failure while to write client and server routes to index html response",
94+
e);
9095
}
9196
}
9297

9398
protected void collectClientViews(
9499
Map<String, AvailableViewInfo> availableViews) {
95100
if (!deploymentConfiguration.isProductionMode()) {
96-
loadLatestDevModeViewsJsonIfNeeded();
101+
loadLatestDevModeFileRoutesJsonIfNeeded();
97102
} else if (lastUpdated == null) {
98103
// initial (and only) registration in production mode:
99104
registerClientRoutes(LocalDateTime.now());
@@ -109,16 +114,17 @@ protected void collectClientViews(
109114

110115
}
111116

112-
private void loadLatestDevModeViewsJsonIfNeeded() {
113-
var devModeViewsJsonFile = deploymentConfiguration.getFrontendFolder()
114-
.toPath().resolve("generated").resolve("views.json").toFile();
115-
if (!devModeViewsJsonFile.exists()) {
116-
LOGGER.warn("Failed to find views.json under {}",
117+
private void loadLatestDevModeFileRoutesJsonIfNeeded() {
118+
var devModeFileRoutesJsonFile = deploymentConfiguration
119+
.getFrontendFolder().toPath().resolve("generated")
120+
.resolve("file-routes.json").toFile();
121+
if (!devModeFileRoutesJsonFile.exists()) {
122+
LOGGER.debug("No file-routes.json found under {}",
117123
deploymentConfiguration.getFrontendFolder().toPath()
118124
.resolve("generated"));
119125
return;
120126
}
121-
var lastModified = devModeViewsJsonFile.lastModified();
127+
var lastModified = devModeFileRoutesJsonFile.lastModified();
122128
var lastModifiedTime = Instant.ofEpochMilli(lastModified)
123129
.atZone(ZoneId.systemDefault()).toLocalDateTime();
124130
if (lastUpdated == null || lastModifiedTime.isAfter(lastUpdated)) {
@@ -127,8 +133,11 @@ private void loadLatestDevModeViewsJsonIfNeeded() {
127133
}
128134

129135
private void registerClientRoutes(LocalDateTime newLastUpdated) {
130-
lastUpdated = newLastUpdated;
131-
clientRouteRegistry.registerClientRoutes(deploymentConfiguration);
136+
var hasClientRoutesRegistered = clientRouteRegistry
137+
.registerClientRoutes(deploymentConfiguration);
138+
if (hasClientRoutesRegistered) {
139+
lastUpdated = newLastUpdated;
140+
}
132141
}
133142

134143
protected void collectServerViews(

packages/java/endpoint/src/main/java/com/vaadin/hilla/startup/RouteUnifyingServiceInitListener.java

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public RouteUnifyingServiceInitListener(
5454
public void serviceInit(ServiceInitEvent event) {
5555
var deploymentConfiguration = event.getSource()
5656
.getDeploymentConfiguration();
57+
LOGGER.debug("deploymentConfiguration.isReactEnabled() = {}",
58+
deploymentConfiguration.isReactEnabled());
5759
if (deploymentConfiguration.isReactEnabled()) {
5860
var routeUnifyingIndexHtmlRequestListener = new RouteUnifyingIndexHtmlRequestListener(
5961
clientRouteRegistry, deploymentConfiguration);

packages/java/endpoint/src/test/java/com/vaadin/hilla/route/ClientRouteRegistryTest.java

+14-13
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public class ClientRouteRegistryTest {
3030
public void when_clearRoutes_isCalled_then_allRoutesAreCleared()
3131
throws IOException {
3232
mockDevelopmentMode();
33-
createMockedDevModeViewsJson();
33+
createMockedDevModeFileRouteJson();
3434

3535
clientRouteRegistry.registerClientRoutes(deploymentConfiguration);
3636
Map<String, ClientViewConfig> allRoutes = clientRouteRegistry
@@ -43,7 +43,7 @@ public void when_clearRoutes_isCalled_then_allRoutesAreCleared()
4343
}
4444

4545
@Test
46-
public void when_developmentMode_and_noViewsJsonFile_then_noRoutesAreRegistered()
46+
public void when_developmentMode_and_noFileRouteJsonFile_then_noRoutesAreRegistered()
4747
throws IOException {
4848

4949
mockDevelopmentMode();
@@ -55,12 +55,12 @@ public void when_developmentMode_and_noViewsJsonFile_then_noRoutesAreRegistered(
5555
}
5656

5757
@Test
58-
public void when_developmentMode_and_emptyViewsJsonFile_then_noRoutesAreRegistered()
58+
public void when_developmentMode_and_emptyFileRouteJsonFile_then_noRoutesAreRegistered()
5959
throws IOException {
6060

6161
mockDevelopmentMode();
6262

63-
projectRoot.newFile("frontend/generated/views.json");
63+
projectRoot.newFile("frontend/generated/file-routes.json");
6464

6565
clientRouteRegistry.registerClientRoutes(deploymentConfiguration);
6666
Map<String, ClientViewConfig> allRoutes = clientRouteRegistry
@@ -106,7 +106,7 @@ public void when_developmentMode_then_loadClientViewsFromFrontendGenerated()
106106
throws IOException {
107107

108108
mockDevelopmentMode();
109-
createMockedDevModeViewsJson();
109+
createMockedDevModeFileRouteJson();
110110

111111
clientRouteRegistry.registerClientRoutes(deploymentConfiguration);
112112
Map<String, ClientViewConfig> allRoutes = clientRouteRegistry
@@ -145,17 +145,18 @@ private void mockDevelopmentMode() throws IOException {
145145
.thenReturn(frontendGeneratedDir.getParentFile());
146146
}
147147

148-
private void createMockedDevModeViewsJson() throws IOException {
149-
var viewsJsonProdAsResource = getClass()
150-
.getResource("/META-INF/VAADIN/views.json");
151-
assert viewsJsonProdAsResource != null;
148+
private void createMockedDevModeFileRouteJson() throws IOException {
149+
var fileRoutesJsonProdAsResource = getClass()
150+
.getResource(ClientRouteRegistry.FILE_ROUTES_JSON_PROD_PATH);
151+
assert fileRoutesJsonProdAsResource != null;
152152
String hierarchicalRoutesAsString = IOUtils.toString(
153-
viewsJsonProdAsResource.openStream(), StandardCharsets.UTF_8);
153+
fileRoutesJsonProdAsResource.openStream(),
154+
StandardCharsets.UTF_8);
154155
String addedDevToRootRoute = hierarchicalRoutesAsString
155156
.replaceFirst("\"route\": \"\",", "\"route\": \"dev\",");
156-
var viewsJsonFile = projectRoot
157-
.newFile("frontend/generated/views.json");
158-
try (PrintWriter writer = new PrintWriter(viewsJsonFile)) {
157+
var fileRoutesJsonFile = projectRoot.newFile("frontend/generated/"
158+
+ ClientRouteRegistry.FILE_ROUTES_JSON_NAME);
159+
try (PrintWriter writer = new PrintWriter(fileRoutesJsonFile)) {
159160
writer.println(addedDevToRootRoute);
160161
}
161162
}

packages/ts/file-router/src/vite-plugin.ts

+5-6
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ export default function vitePluginFileSystemRouter({
7070
_logger.info(`The output directory: ${String(_outDir)}`);
7171

7272
runtimeUrls = {
73-
json: new URL('views.json', isDevMode ? _generatedDir : _outDir),
74-
code: new URL('views.ts', _generatedDir),
73+
json: new URL('file-routes.json', isDevMode ? _generatedDir : _outDir),
74+
code: new URL('file-routes.ts', _generatedDir),
7575
};
7676
},
7777
async buildStart() {
@@ -89,10 +89,9 @@ export default function vitePluginFileSystemRouter({
8989
return;
9090
}
9191

92-
generateRuntimeFiles(_viewsDir, runtimeUrls, extensions, _logger).catch((e: unknown) =>
93-
_logger.error(String(e)),
94-
);
95-
server.hot.send({ type: 'full-reload' });
92+
generateRuntimeFiles(_viewsDir, runtimeUrls, extensions, _logger)
93+
.then(() => server.hot.send({ type: 'full-reload' }))
94+
.catch((e: unknown) => _logger.error(String(e)));
9695
};
9796

9897
server.watcher.on('add', changeListener);

packages/ts/file-router/src/vite-plugin/createRoutesFromMeta.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ export default routes;
123123
],
124124
);
125125

126-
const file = createSourceFile(routeDeclaration, 'views.ts');
127-
126+
const file = createSourceFile(routeDeclaration, 'file-routes.ts');
127+
// also keep the old file temporarily for compatibility purposes:
128+
const tempFile = createSourceFile(routeDeclaration, 'views.ts');
129+
printer.printFile(tempFile);
128130
return printer.printFile(file);
129131
}

packages/ts/file-router/src/vite-plugin/generateRuntimeFiles.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,17 @@ export async function generateRuntimeFiles(
6060
logger.info('Collected file-based routes');
6161
const runtimeRoutesCode = createRoutesFromMeta(routeMeta, urls);
6262
const viewConfigJson = await createViewConfigJson(routeMeta);
63-
63+
const tempUrl = new URL('views.ts', urls.code.href);
6464
await Promise.all([
6565
generateRuntimeFile(urls.json, viewConfigJson).then(() =>
6666
logger.info(`Frontend route list is generated: ${String(urls.json)}`),
6767
),
6868
generateRuntimeFile(urls.code, runtimeRoutesCode).then(() =>
69-
logger.info(`Views module is generated: ${String(urls.code)}`),
69+
logger.info(`File Route module is generated: ${String(urls.code)}`),
70+
),
71+
// also keep the old file temporarily for compatibility purposes:
72+
generateRuntimeFile(tempUrl, runtimeRoutesCode).then(() =>
73+
logger.info(`Views module is generated: ${String(tempUrl)}`),
7074
),
7175
]);
7276
}

packages/ts/file-router/test/vite-plugin/createRoutesFromMeta.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ describe('@vaadin/hilla-file-router', () => {
1717
dir = pathToFileURL(join(tmpdir(), 'file-router/'));
1818
meta = createTestingRouteMeta(new URL('./views/', dir));
1919
runtimeUrls = {
20-
json: new URL('server/views.json', dir),
21-
code: new URL('generated/views.ts', dir),
20+
json: new URL('server/file-routes.json', dir),
21+
code: new URL('generated/file-routes.ts', dir),
2222
};
2323
});
2424

packages/ts/file-router/test/vite-plugin/generateRuntimeFiles.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ describe('@vaadin/hilla-file-router', () => {
2121

2222
viewsDir = new URL('views/', tmp);
2323
runtimeUrls = {
24-
json: new URL('server/views.json', tmp),
25-
code: new URL('generated/views.ts', tmp),
24+
json: new URL('server/file-routes.json', tmp),
25+
code: new URL('generated/file-routes.ts', tmp),
2626
};
2727

2828
await createTestingRouteFiles(viewsDir);

0 commit comments

Comments
 (0)