diff --git a/.changeset/create-croco-app-ssr-route-components.md b/.changeset/create-croco-app-ssr-route-components.md new file mode 100644 index 000000000..86f63727f --- /dev/null +++ b/.changeset/create-croco-app-ssr-route-components.md @@ -0,0 +1,6 @@ +--- +"create-croco-app": patch +"@croco/frontend-react": patch +--- + +Wire SSR template routes to generated page component values and expose the page data function type used by the SSR fixture. diff --git a/packages/create-croco-app/src/tests/templates-build.spec.ts b/packages/create-croco-app/src/tests/templates-build.spec.ts index e3b7c432b..5b2983c69 100644 --- a/packages/create-croco-app/src/tests/templates-build.spec.ts +++ b/packages/create-croco-app/src/tests/templates-build.spec.ts @@ -28,6 +28,12 @@ function checkFileContains(template: string, filePath: string[], pattern: string expect(content).toMatch(pattern); } +function checkFileDoesNotContain(template: string, filePath: string[], pattern: string | RegExp) { + const content = readFileSync(templatePath(template, ...filePath), "utf-8"); + + expect(content).not.toMatch(pattern); +} + function readJsonTemplate(template: string, ...paths: string[]): Record { const content = readFileSync(templatePath(template, ...paths), "utf-8"); @@ -42,6 +48,17 @@ function listPageFiles(template: string): string[] { .map((entry) => join(entry.parentPath, entry.name).replace(`${pagesDir}/`, "")); } +function checkSsrRouteComponent(template: string) { + const routePath = ["apps", "console-web", "pages", "route.ts"]; + + checkFileContains(template, routePath, /import Page from ["']\.\/index\/Page["'];/); + checkFileContains(template, routePath, /type PageRouteDefinition/); + checkFileContains(template, routePath, /component:\s*Page,/); + checkFileContains(template, routePath, /satisfies PageRouteDefinition/); + checkFileDoesNotContain(template, routePath, /import type \{ default as Page/); + checkFileDoesNotContain(template, routePath, /component:\s*undefined/); +} + function checkSpaBeSplitStructure() { checkFileExists("spa-be-split", "apps", "api-server", "package.json.hbs"); readJsonTemplate("spa-be-split", "apps", "api-server", "package.json.hbs"); @@ -88,6 +105,7 @@ function checkSsrLambdaStructure() { ["apps", "console-web", "pages", "index", "Page.tsx"], /export default function \w+\(/, ); + checkSsrRouteComponent("ssr-lambda"); } function checkContainerFullstackStructure() { @@ -113,6 +131,7 @@ function checkContainerFullstackStructure() { ["apps", "console-web", "pages", "route.ts"], /mode:\s*['"]ssr['"]/, ); + checkSsrRouteComponent("container-fullstack"); } describe.each(["spa-be-split", "ssr-lambda", "container-fullstack"])("Template: %s", (template) => { diff --git a/packages/create-croco-app/templates/container-fullstack/apps/console-web/pages/route.ts b/packages/create-croco-app/templates/container-fullstack/apps/console-web/pages/route.ts index 47447e649..034426bf3 100644 --- a/packages/create-croco-app/templates/container-fullstack/apps/console-web/pages/route.ts +++ b/packages/create-croco-app/templates/container-fullstack/apps/console-web/pages/route.ts @@ -1,9 +1,11 @@ -import type { default as PageComponent } from "./index/Page"; -import { defineRoute, head } from "@croco/meta-vite"; +import { defineRoute, head, type PageRouteDefinition } from "@croco/meta-vite"; +import Page from "./index/Page"; -export default defineRoute({ +const route = { path: "/", mode: "ssr", - component: undefined as PageComponent, + component: Page, head: head({ title: "Croco" }), -}); +} satisfies PageRouteDefinition; + +export default defineRoute(route); diff --git a/packages/create-croco-app/templates/ssr-lambda/apps/console-web/pages/route.ts b/packages/create-croco-app/templates/ssr-lambda/apps/console-web/pages/route.ts index 0ffb1bf43..29c8dbe0a 100644 --- a/packages/create-croco-app/templates/ssr-lambda/apps/console-web/pages/route.ts +++ b/packages/create-croco-app/templates/ssr-lambda/apps/console-web/pages/route.ts @@ -1,9 +1,11 @@ -import type { default as Page } from "./index/Page"; -import { defineRoute, head } from "@croco/meta-vite"; +import { defineRoute, head, type PageRouteDefinition } from "@croco/meta-vite"; +import Page from "./index/Page"; -export default defineRoute({ +const route = { path: "/", mode: "ssr", - component: Page satisfies Page, + component: Page, head: head({ title: "Croco Console" }), -}); +} satisfies PageRouteDefinition; + +export default defineRoute(route); diff --git a/packages/frontend-react/src/index.ts b/packages/frontend-react/src/index.ts index 8d8a20fa3..4446e301b 100644 --- a/packages/frontend-react/src/index.ts +++ b/packages/frontend-react/src/index.ts @@ -15,4 +15,4 @@ export { usePageData, usePageMeta, } from "./libs/hooks/usePageData"; -export type { CrocoPageContext } from "./libs/types"; +export type { CrocoDataFn, CrocoPageContext } from "./libs/types"; diff --git a/packages/frontend-react/src/tests/public-types.spec.ts b/packages/frontend-react/src/tests/public-types.spec.ts new file mode 100644 index 000000000..4e182a598 --- /dev/null +++ b/packages/frontend-react/src/tests/public-types.spec.ts @@ -0,0 +1,11 @@ +import { describe, expectTypeOf, it } from "vitest"; + +import type { CrocoDataFn, CrocoPageContext } from "../index"; + +describe("public types", () => { + it("exports CrocoDataFn from the package entrypoint", () => { + expectTypeOf>().parameters.toEqualTypeOf< + [CrocoPageContext] + >(); + }); +});