Skip to content

Commit

Permalink
feat: v2.2.0 refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastien Ringrose committed Mar 9, 2024
1 parent 787c258 commit aba1aa9
Show file tree
Hide file tree
Showing 48 changed files with 1,711 additions and 1,729 deletions.
26 changes: 21 additions & 5 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ permissions:
contents: read

jobs:
profile-deno:
runs-on: ubuntu-latest

steps:
- name: setup repo
uses: actions/checkout@v3

- name: setup Deno
uses: denoland/setup-deno@v1
with:
deno-version: v1.x

- name: Run profile
run: deno task profile

unit-test-deno:
runs-on: ubuntu-latest

Expand All @@ -39,9 +54,6 @@ jobs:
- name: run tests
run: deno task test

# - name: Run profile
# run: deno task profile

test-run-bun:
runs-on: ubuntu-latest

Expand All @@ -58,7 +70,9 @@ jobs:
run: bun install

- name: bun run
run: npm run test:bun && kill -9 <(lsof -i :7777 -t)
run: npm run test:bun
after_script:
- pkill bun

test-run-wrangler:
runs-on: ubuntu-latest
Expand All @@ -74,4 +88,6 @@ jobs:
run: npm install -g wrangler

- name: wrangler dev
run: npm run test:cfw && kill -9 <(lsof -i :7777 -t)
run: npm run test:cfw
after_script:
- pkill node
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes
File renamed without changes
28 changes: 21 additions & 7 deletions examples/preact/document.ts → example/preactSSR/document.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
export default (tags: Record<string, string>) => `<!DOCTYPE html>
export default (input: {
title: string;
entrypoint: string;
ssrHTML: string;
serverState?: Record<string, unknown>;
}) => `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/assets/twemoji_chick.svg">
${tags && tags.title}
<meta name="description" content="The Featherweight Deno SSR Library">
<title>${input.title}</title>
<meta name="description" content="Featherweight apps on the edge">
<meta name="keywords" content="deno, edge, serverless, preact, peko, cloudflare, bun, typescript, server">
${tags && tags.modulepreload}
<script modulepreload="true" type="module" src="${
input.entrypoint
}"></script>
<style>
html, body, #root {
Expand Down Expand Up @@ -45,9 +53,15 @@ export default (tags: Record<string, string>) => `<!DOCTYPE html>
</head>
<body>
<div id="root">
${tags.appHTML}
${input.ssrHTML}
</div>
${tags && tags.hydrationScript}
<script type="module">
import { hydrate } from "https://npm.reversehttp.com/preact,preact/hooks,htm/preact,preact-render-to-string";
import About from "${input.entrypoint}";
hydrate(About(${JSON.stringify(
input.serverState
)}), document.getElementById("root"))
</script
</body>
</html>`
</html>`;
162 changes: 162 additions & 0 deletions example/preactSSR/router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import {
Router,
RequestContext,
logger,
sse,
cacher,
ssr,
file,
} from "../../index.ts"; //"https://deno.land/x/peko/mod.ts"
import { renderToString } from "preact-render-to-string";

// Preact page components and HTML template for ssrHandler render logic
import Home from "./src/pages/Home.ts";
import About from "./src/pages/About.ts";
import htmlTemplate from "./document.ts";

// esbuild bundling for app TS files
import * as esbuild from "esbuild";

const env: Record<string, string> =
(typeof Deno !== "undefined" && Deno.env.toObject()) ||
(typeof process !== "undefined" && process.env) ||
(typeof env !== "undefined" && env) ||
{};

const router = new Router();
router.use(logger(console.log));

// FRONTEND PAGES
router.get("/", {
// use cacher to serve responses from cache in prod env
middleware: env.ENVIRONMENT === "production" ? cacher() : [],
handler: ssr(
() => {
const ssrHTML = renderToString(Home(), null);
return htmlTemplate({
title: "Peko",
ssrHTML,
entrypoint: "/src/pages/Home.ts",
});
},
{
headers: new Headers({
// instruct browser to cache page in prod env
"Cache-Control":
env.ENVIRONMENT === "production"
? "max-age=86400, stale-while-revalidate=86400"
: "no-store",
}),
}
),
});

router.get(
"/about",
(ctx) => {
ctx.state = {
request_time: `${Date.now()}`,
...env,
};
},
ssr((ctx) => {
const ssrHTML = renderToString(About(ctx.state), null);
return htmlTemplate({
title: "Peko | About",
ssrHTML,
entrypoint: "/src/pages/About.ts",
});
})
);

// STATIC FILES
// dynamic URL param for filename, always cache
router.get("/assets/:filename", cacher(), async (ctx) =>
(
await file(
new URL(
`https://raw.githubusercontent.com/sejori/peko/main/example/preact/assets/${ctx.params.filename}`
),
{
headers: new Headers({
// instruct browser to cache file in prod env
"Cache-Control":
env.ENVIRONMENT === "production"
? "max-age=86400, stale-while-revalidate=86400"
: "no-store",
}),
}
)
)(ctx)
);

// BUNDLED TS FILES
// dynamic URL param for filename, always cache
router.get("/src/:filename", cacher(), async (ctx) =>
(
await file(
new URL(
`https://raw.githubusercontent.com/sejori/peko/main/example/preact/src/${ctx.params.filename}`
),
{
transform: async (contents) => {
const reader = contents.getReader();
let result = "";
let { done, value } = await reader.read();
while (!done) {
result += new TextDecoder().decode(value);
({ done, value } = await reader.read());
}
const esbuildResult = await esbuild.build({
bundle: true,
write: false,
stdin: {
contents: result,
},
format: "esm",
target: "es2022",
loader: {
".ts": "ts",
},
});

const bundle = esbuildResult.outputFiles[0].text;
console.log(bundle);
return bundle;
},
headers: new Headers({
"Content-Type": "application/javascript",
// instruct browser to cache file in prod env
"Cache-Control":
env.ENVIRONMENT === "production"
? "max-age=86400, stale-while-revalidate=86400"
: "no-store",
}),
}
)
)(ctx)
);

// API FUNCTIONALITY
const demoEventTarget = new EventTarget();
// shorthand route adding
router.get("/sse", (ctx: RequestContext) => {
setInterval(() => {
demoEventTarget.dispatchEvent(
new CustomEvent("send", { detail: Math.random() })
);
}, 2500);

return sse(demoEventTarget)(ctx);
});
// full route object adding
router.addRoute({
path: "/api/parrot",
method: "POST",
handler: async (ctx: RequestContext) => {
const body = await ctx.request.text();
return new Response(`Parrot sqwarks: ${body}`);
},
});

export default router;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect } from "preact/hooks";
import { html } from "htm/preact";
import List from "./List.js";
import { useLocalState } from "../hooks/localstate.js";
import List from "./List.ts";
import { useLocalState } from "../hooks/localstate.ts";

const App = () => {
const [dataArray, setDataArray] = useLocalState("dataArray");
Expand Down Expand Up @@ -31,7 +31,7 @@ const App = () => {
<button
style=${btnLgStyle}
onClick=${() =>
setDataArray((dataArray) => [
setDataArray((dataArray: string[]) => [
...dataArray,
`Item ${dataArray.length}`,
])}
Expand All @@ -41,7 +41,9 @@ const App = () => {
<button
style=${btnLgStyle}
onClick=${() =>
setDataArray((dataArray) => dataArray.slice(0, dataArray.length - 1))}
setDataArray((dataArray: string[]) =>
dataArray.slice(0, dataArray.length - 1)
)}
>
remove item
</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { html } from "htm/preact";

const Layout = ({ navColor, navLink, children }) => {
const Layout = ({
navColor,
navLink,
children,
}: {
navColor: string;
navLink: string;
children: unknown;
}) => {
return html`
<nav style=${navStyle(navColor)}>
<div class="container align-center">
Expand Down Expand Up @@ -54,7 +62,7 @@ const Layout = ({ navColor, navLink, children }) => {
`;
};

const navStyle = (navColor) => `
const navStyle = (navColor: string) => `
width: 100%;
display: flex;
flex-direction: column;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from "preact/hooks";
import { html } from "htm/preact";

const List = ({ data }) => {
const List = ({ data }: { data: string[] }) => {
// takes a data prop
// how many clicks have we counted? Default to 0
const [count, setCount] = useState(0);
Expand All @@ -16,7 +16,7 @@ const List = ({ data }) => {
<ul>
${data &&
data.map(
(i) => html`
(i: string) => html`
<li>${i}: <button onClick=${handleClick}>Click me</button></li>
`
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { useState, useEffect } from "preact/hooks";

// INITIAL STATE
const initialState = {
const initialState: Record<string, unknown> = {
dataArray: ["Item 0", "Item 1", "Item 2"],
};

// listeners object stores arrays of all state variable setters for each key
const listeners = {};
const listeners: Record<string, ((x: unknown) => unknown)[]> = {};
Object.keys(initialState).forEach((key) => (listeners[key] = []));

/**
*
* @param {string} key state variable name
* @returns [state, setState]
*/
const useLocalState = (key) => {
const useLocalState = (key: string) => {
// return regular state if no localStorage (server-side renders)
if (typeof localStorage === "undefined") return useState(initialState[key]);

Expand Down Expand Up @@ -51,7 +51,7 @@ const getLocalState = () => {
* @param {string} key state variable name
* @returns {*} state variable value
*/
const getLocalStateValue = (key) => {
const getLocalStateValue = (key: string) => {
const localState = getLocalState();
if (localState[key]) return localState[key];
throw new Error(
Expand All @@ -64,7 +64,7 @@ const getLocalStateValue = (key) => {
* @param {string} key state variable name
* @param {*} value state variable value
*/
const setLocalStateValue = (key, value) => {
const setLocalStateValue = (key: string, value: unknown) => {
// update all state listeners before setting in case we cannot set localStorage
// (e.g. private browsing iOS Safari)
listeners[key].forEach((setState) => setState(value));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { html } from "htm/preact";

import Layout from "../components/Layout.js";
import App from "../components/App.js";
import Layout from "../components/Layout.ts";
import App from "../components/App.ts";

const About = (props) => {
const About = (props: Record<string, unknown>) => {
return html`
<${Layout} navLink="" navColor="blueviolet">
<div style="display: flex; justify-content: space-around; flex-wrap: wrap;">
Expand Down
Loading

1 comment on commit aba1aa9

@deno-deploy
Copy link

@deno-deploy deno-deploy bot commented on aba1aa9 Mar 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failed to deploy:

Module not found "file:///src/scripts/deno.ts".

Please sign in to comment.