feat: really crude server:setup logic

This commit is contained in:
Ayo 2023-10-10 17:49:33 +02:00
parent 92db1c9059
commit 9608cb6f56
5 changed files with 66 additions and 13 deletions

8
package-lock.json generated
View file

@ -5,7 +5,8 @@
"packages": { "packages": {
"": { "": {
"dependencies": { "dependencies": {
"nitropack": "latest" "nitropack": "latest",
"ultrahtml": "^1.5.2"
} }
}, },
"node_modules/@cloudflare/kv-asset-handler": { "node_modules/@cloudflare/kv-asset-handler": {
@ -3624,6 +3625,11 @@
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz",
"integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==" "integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw=="
}, },
"node_modules/ultrahtml": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.5.2.tgz",
"integrity": "sha512-qh4mBffhlkiXwDAOxvSGxhL0QEQsTbnP9BozOK3OYPEGvPvdWzvAUaXNtUSMdNsKDtuyjEbyVUPFZ52SSLhLqw=="
},
"node_modules/uncrypto": { "node_modules/uncrypto": {
"version": "0.1.3", "version": "0.1.3",
"resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz",

View file

@ -9,6 +9,7 @@
"build:preview": "npm run build && npm run preview" "build:preview": "npm run build && npm run preview"
}, },
"dependencies": { "dependencies": {
"nitropack": "latest" "nitropack": "latest",
"ultrahtml": "^1.5.2"
} }
} }

View file

@ -1,3 +1,5 @@
import { ELEMENT_NODE, parse, walkSync } from "ultrahtml";
export default eventHandler(async (event) => { export default eventHandler(async (event) => {
const rawPath = const rawPath =
event.path[event.path.length - 1] === "/" event.path[event.path.length - 1] === "/"
@ -10,14 +12,58 @@ export default eventHandler(async (event) => {
if (!html) html = await useStorage().getItem(fallback); if (!html) html = await useStorage().getItem(fallback);
if (!html) html = await useStorage().getItem(getPath("/404.html")); if (!html) html = await useStorage().getItem(getPath("/404.html"));
// temporary; use ultrahtml later // transforms
const registryScript = const transforms = [insertRegistry, doSetUp];
'<script type="module" src="./.output/registry.js"></script>'; if (html) {
html = html.toString().replace("</head>", registryScript + "</head>"); for (const transform of transforms) {
html = transform(html.toString());
}
}
return html ?? new Response("Not found", { status: 404 }); return html ?? new Response("Not found", { status: 404 });
}); });
function getPath(filename: string) { function getPath(filename: string) {
return `assets/pages${filename}`; return `assets/pages${filename}`;
} }
function insertRegistry(html: string): string {
// temporary; use ultrahtml later
const registryScript =
'<script type="module" src="./.output/registry.js"></script>';
return html.toString().replace("</head>", registryScript + "</head>");
}
function doSetUp(html: string) {
const ast = parse(html);
const serverScripts = [];
walkSync(ast, (node) => {
const { attributes } = node;
const attributeKeys = Object.keys(attributes ?? {});
const isServerScript = attributeKeys.some((key) => key.includes("server:"));
const isInHead = node.parent?.name === "head";
if (
node.type === ELEMENT_NODE &&
node.name === "script" &&
isServerScript &&
isInHead
) {
const scripts = node.children.map((child) => child.value);
serverScripts.push(scripts.join(" "));
}
});
const setupMap = {};
serverScripts.forEach((script: string) => {
console.log(script);
const constructor = `
new Function(\`${script}\`);
`;
const evalStore = eval(constructor);
Object.assign(setupMap, new evalStore());
console.log(">>> from server", setupMap);
});
return html.replace("{{name}}", setupMap["name"]);
}

View file

@ -9,7 +9,7 @@ export default class HelloWorld extends WebComponent {
let count = 0; let count = 0;
this.onclick = () => { this.onclick = () => {
console.log("Clicked!"); console.log("Clicked!");
this.setAttribute("name", `I was clicked ${++count} times`); this.setAttribute("name", `I was clicked ${++count} times!`);
}; };
this.setAttribute("title", "Click me please"); this.setAttribute("title", "Click me please");
} }

View file

@ -4,9 +4,9 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hello Nitro</title> <title>Hello Nitro</title>
<script setup> <script server:setup>
// define logic that runs on the server const name = "AYOs";
const name = "Ayo"; return { name };
</script> </script>
</head> </head>
<body> <body>
@ -16,11 +16,11 @@
</div> </div>
<span>some text</span> <span>some text</span>
<clickable-text></clickable-text> <clickable-text></clickable-text>
<script> <!-- <script>
const helloWorld = document.querySelector("hello-world"); const helloWorld = document.querySelector("hello-world");
setTimeout(() => { setTimeout(() => {
helloWorld.setAttribute("name", "Nitro"); helloWorld.setAttribute("name", "Nitro");
}, 2000); }, 2000);
</script> </script> -->
</body> </body>
</html> </html>