Skip to content

Commit

Permalink
feat: Hattip support
Browse files Browse the repository at this point in the history
  • Loading branch information
magne4000 committed Jun 26, 2024
1 parent 579744b commit a190e3a
Show file tree
Hide file tree
Showing 42 changed files with 1,071 additions and 19 deletions.
3 changes: 3 additions & 0 deletions examples/hattip-app/.test-dev.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { testRun } from "./.testRun";

testRun("pnpm run dev");
8 changes: 8 additions & 0 deletions examples/hattip-app/.test-preview.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { testRun } from "./.testRun";

testRun("pnpm run preview --port 3000", {
doNotFailOnWarning: true,
serverIsReadyMessage: "Starting local server",
serverIsReadyDelay: 2000,
serverUrl: "http://127.0.0.1:3000",
});
63 changes: 63 additions & 0 deletions examples/hattip-app/.testRun.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { expect, fetchHtml, getServerUrl, page, run, test } from "@brillout/test-e2e";

export { testRun };

let isProd: boolean;

function testRun(cmd: `pnpm run ${"dev" | "preview"}${string}`, options?: Parameters<typeof run>[1]) {
run(cmd, options);

isProd = cmd !== "pnpm run dev";

testUrl({
url: "/",
title: "My Vike App",
text: "built with https://github.com/vikejs/vike-solid",
textHydration: "Rendered to HTML",
});

testUrl({
url: "/star-wars",
title: "6 Star Wars Movies",
text: "A New Hope",
});

testUrl({
url: "/star-wars/3",
title: "Return of the Jedi",
text: "1983-05-25",
});
}

function testUrl({
url,
title,
text,
textHydration,
noSSR,
}: {
url: string;
title: string;
text: string;
textHydration?: string;
counter?: true;
noSSR?: true;
}) {
test(url + " (HTML)", async () => {
const html = await fetchHtml(url);
if (!noSSR) {
expect(html).toContain(text);
}
expect(getTitle(html)).toBe(title);
});
test(url + " (Hydration)", async () => {
await page.goto(getServerUrl() + url);
const body = await page.textContent("body");
expect(body).toContain(textHydration ?? text);
});
}

function getTitle(html: string) {
const title = html.match(/<title>(.*?)<\/title>/i)?.[1];
return title;
}
35 changes: 35 additions & 0 deletions examples/hattip-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
This app has been created with [Bati](https://batijs.dev) using the following flags: `--solid --hattip`

# About this app
This app is ready to start. It's powered by [Vike](https://vike.dev) and [SolidJS](https://www.solidjs.com/guides/getting-started).

### `/pages/+config.ts`

Such `+` files are [the interface](https://vike.dev/config) between Vike and your code. It defines:
- A default [`<Layout>` component](https://vike.dev/Layout) (that wraps your [`<Page>` components](https://vike.dev/Page)).
- A default [`title`](https://vike.dev/head).
- Default [`<head>` tags](https://vike.dev/head).

### Routing

[Vike's built-in router](https://vike.dev/routing) lets you choose between:
- [Filesystem Routing](https://vike.dev/filesystem-routing) (the URL of a page is determined based on where its `+Page.jsx` file is located on the filesystem)
- [Route Strings](https://vike.dev/route-string)
- [Route Functions](https://vike.dev/route-function)

### `/pages/_error/+Page.jsx`

The [error page](https://vike.dev/error-page) which is rendered when errors occur.

### `/pages/+onPageTransitionStart.ts` and `/pages/+onPageTransitionEnd.ts`

The [`onPageTransitionStart()` hook](https://vike.dev/onPageTransitionStart), together with [`onPageTransitionEnd()`](https://vike.dev/onPageTransitionEnd), enables you to implement page transition animations.

### SSR

SSR is enabled by default. You can [disable it](https://vike.dev/ssr) for all your pages or only for some pages.

### HTML Streaming

You can enable/disable [HTML streaming](https://vike.dev/streaming) for all your pages, or only for some pages while still using it for others.

36 changes: 36 additions & 0 deletions examples/hattip-app/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions examples/hattip-app/components/Link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createMemo } from "solid-js";
import { usePageContext } from "vike-solid/usePageContext";

export function Link(props: { href: string; children: string }) {
const pageContext = usePageContext();
const isActive = createMemo(() =>
props.href === "/" ? pageContext.urlPathname === props.href : pageContext.urlPathname.startsWith(props.href),
);
return (
<a href={props.href} class={isActive() ? "is-active" : undefined}>
{props.children}
</a>
);
}
5 changes: 5 additions & 0 deletions examples/hattip-app/database/todoItems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
interface TodoItem {
text: string;
}

export type { TodoItem };
36 changes: 36 additions & 0 deletions examples/hattip-app/hattip-entry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { createTodoHandler } from "./server/create-todo-handler";
import { vikeHandler } from "./server/vike-handler";
import type { HattipHandler } from "@hattip/core";
import { createRouter, type RouteHandler } from "@hattip/router";

interface Middleware<
Context extends Record<string | number | symbol, unknown>,
> {
(
request: Request,
context: Context,
): Response | void | Promise<Response> | Promise<void>;
}

function handlerAdapter<
Context extends Record<string | number | symbol, unknown>,
>(handler: Middleware<Context>): RouteHandler<unknown, unknown> {
return (context) => {
const rawContext = context as unknown as Record<string, unknown>;
rawContext.context ??= {};
return handler(context.request, rawContext.context as Context);
};
}

const router = createRouter();

router.post("/api/todo/create", handlerAdapter(createTodoHandler));

/**
* Vike route
*
* @link {@see https://vike.dev}
**/
router.use(handlerAdapter(vikeHandler));

export default router.buildHandler() as HattipHandler;
15 changes: 15 additions & 0 deletions examples/hattip-app/layouts/HeadDefault.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* eslint-disable solid/no-innerhtml */

// Default <head> (can be overridden by pages)

import logoUrl from "../assets/logo.svg";

export default function HeadDefault() {
return (
<>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Demo showcasing Vike" />
<link rel="icon" href={logoUrl} />
</>
);
}
75 changes: 75 additions & 0 deletions examples/hattip-app/layouts/LayoutDefault.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import "./style.css";

import type { JSX } from "solid-js";
import logoUrl from "../assets/logo.svg";
import { Link } from "../components/Link.js";

export default function LayoutDefault(props: { children?: JSX.Element }) {
return (
<div
style={{
display: "flex",
"max-width": "900px",
margin: "auto",
}}
>
<Sidebar>
<Logo />
<Link href="/">Welcome</Link>
<Link href="/todo">Todo</Link>
<Link href="/star-wars">Data Fetching</Link>
</Sidebar>
<Content>{props.children}</Content>
</div>
);
}

function Sidebar(props: { children: JSX.Element }) {
return (
<div
id="sidebar"
style={{
padding: "20px",
"flex-shrink": 0,
display: "flex",
"flex-direction": "column",
"line-height": "1.8em",
"border-right": "2px solid #eee",
}}
>
{props.children}
</div>
);
}

function Content(props: { children: JSX.Element }) {
return (
<div id="page-container">
<div
id="page-content"
style={{
padding: "20px",
"padding-bottom": "50px",
"min-height": "100vh",
}}
>
{props.children}
</div>
</div>
);
}

function Logo() {
return (
<div
style={{
"margin-top": "20px",
"margin-bottom": "10px",
}}
>
<a href="/">
<img src={logoUrl} height={64} width={64} alt="logo" />
</a>
</div>
);
}
29 changes: 29 additions & 0 deletions examples/hattip-app/layouts/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* Links */
a {
text-decoration: none;
}
#sidebar a {
padding: 2px 10px;
margin-left: -10px;
}
#sidebar a.is-active {
background-color: #eee;
}

/* Reset */
body {
margin: 0;
font-family: sans-serif;
}
* {
box-sizing: border-box;
}

/* Page Transition Animation */
#page-content {
opacity: 1;
transition: opacity 0.3s ease-in-out;
}
body.page-is-transitioning #page-content {
opacity: 0;
}
35 changes: 35 additions & 0 deletions examples/hattip-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "my-app",
"version": "0.0.1",
"description": "",
"type": "module",
"scripts": {
"dev": "hattip serve ./hattip-entry.ts --client",
"build": "NODE_ENV=production hattip build ./hattip-entry.ts --target es2022 --client",
"preview": "pnpm run build && wrangler pages dev",
"deploy": "pnpm run build && wrangler pages deploy",
"test": "tsc --noEmit"
},
"keywords": [],
"author": "",
"devDependencies": {
"@auth/core": "^0.34.1",
"@hattip/adapter-cloudflare-workers": "^0.0.46",
"@hattip/adapter-node": "^0.0.46",
"@hattip/vite": "^0.0.46",
"typescript": "^5.5.2",
"vike-cloudflare": "^0.0.3",
"wrangler": "^3.61.0"
},
"dependencies": {
"@hattip/core": "^0.0.46",
"@hattip/router": "^0.0.46",
"cross-fetch": "^4.0.0",
"hattip": "^0.0.33",
"lowdb": "^7.0.1",
"solid-js": "^1.8.17",
"vike": "^0.4.177",
"vike-solid": "^0.6.2",
"vite": "^5.3.1"
}
}
13 changes: 13 additions & 0 deletions examples/hattip-app/pages/+config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import vikeSolid from "vike-solid/config";
import type { Config } from "vike/types";
import Head from "../layouts/HeadDefault.js";
import Layout from "../layouts/LayoutDefault.js";

// Default config (can be overridden by pages)
export default {
Layout,
Head,
title: "My Vike App",
stream: "web",
extends: vikeSolid,
} satisfies Config;
6 changes: 6 additions & 0 deletions examples/hattip-app/pages/+onPageTransitionEnd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { OnPageTransitionEndAsync } from "vike/types";

export const onPageTransitionEnd: OnPageTransitionEndAsync = async () => {
console.log("Page transition end");
document.querySelector("body")?.classList.remove("page-is-transitioning");
};
6 changes: 6 additions & 0 deletions examples/hattip-app/pages/+onPageTransitionStart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { OnPageTransitionStartAsync } from "vike/types";

export const onPageTransitionStart: OnPageTransitionStartAsync = async () => {
console.log("Page transition start");
document.querySelector("body")?.classList.add("page-is-transitioning");
};
Loading

0 comments on commit a190e3a

Please sign in to comment.