cache example

main
Ethan Niser 2023-09-17 00:59:44 -05:00
parent 5486079888
commit bbf3c6f57d
4 changed files with 74 additions and 14 deletions

@ -4,7 +4,7 @@
"type": "module",
"scripts": {
"dev": "concurrently \"bun run --hot src/main.ts\" \"bun run uno:dev\" \"bun run liveReload\"",
"liveReload": "bun run src/lib/liveReload.ts",
"liveReload": "bun run src/beth/liveReload.ts",
"start": "bun run uno && bun run src/main.ts",
"db:push": "bunx drizzle-kit push:sqlite",
"db:studio": "bunx drizzle-kit studio",

@ -8,6 +8,29 @@ export const BaseHtml = ({ children }: PropsWithChildren) => (
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>THE BETH STACK</title>
<script src="https://unpkg.com/htmx.org@1.9.5"></script>
<script>
{`
(function () {
htmx.defineExtension("revalidate", {
onEvent: function (name, evt) {
if (name === "htmx:configRequest") {
var revalidationTag = evt.srcElement.getAttribute("hx-revalidate");
console.log("revalidationTag", revalidationTag)
if (revalidationTag) {
// Split the string into an array based on comma and trim spaces
var tags = revalidationTag.split(',').map(function(tag) {
return tag.trim();
});
// Convert array to JSON and set it to the header
evt.detail.headers["HX-Revalidate"] = JSON.stringify(tags);
}
}
},
});
})();
`}
</script>
<script src="https://unpkg.com/hyperscript.org@0.9.11"></script>
<link
rel="stylesheet"
@ -38,6 +61,6 @@ export const BaseHtml = ({ children }: PropsWithChildren) => (
`}
</script>
</head>
<body>{children}</body>
<body hx-ext="revalidate">{children}</body>
</html>
);

@ -1,16 +1,52 @@
import Elysia from "elysia";
import { BaseHtml } from "../components/base";
import { ctx } from "../context";
import { renderToString } from "beth-jsx";
import { persistedCache, revalidateTag } from "../beth/cache";
export const index = new Elysia().use(ctx).get("/", ({ html }) =>
html(
<BaseHtml>
<div
class="flex w-full h-screen justify-center items-center"
hx-get="/api/todos"
hx-swap="innerHTML"
hx-trigger="load"
/>
</BaseHtml>
)
);
const start = Date.now();
const getTime = async () => (Date.now() - start) / 1000;
const cachedGetTime = persistedCache(getTime, "getTime", {
tags: ["time"],
revalidate: 2,
});
export const index = new Elysia()
.use(ctx)
.onRequest(({ request }) => {
const revalidate = request.headers.get("HX-Revalidate");
if (revalidate) {
const tags = JSON.parse(revalidate);
tags.forEach((tag: string) => {
revalidateTag(tag);
});
}
})
.get("/test", async () => {
const time = await cachedGetTime();
return renderToString(() => <p safe>{time}</p>);
})
.get("/", async ({ set }) => {
set.headers["content-type"] = "text/html";
return renderToString(() => (
<BaseHtml>
<h1>cache revalidates on two second interval</h1>
<button hx-get="/test" hx-target="#foo" hx-swap="beforeend">
click me to get time (cached)
</button>
<br />
<br />
<button
hx-get="/test"
hx-target="#foo"
hx-swap="beforeend"
hx-revalidate="time"
>
click me (revalidate now)
</button>
<div id="foo"></div>
</BaseHtml>
));
});

@ -44,5 +44,6 @@ declare namespace JSX {
["hx-delete"]?: DeleteRoutes;
["hx-patch"]?: PatchRoutes;
_?: string;
["hx-revalidate"]?: string;
}
}