Skip to content

Commit

Permalink
Handle errors (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
mxdvl authored Aug 24, 2024
1 parent 65cfec4 commit 749b3dd
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 48 deletions.
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mxdvl/mononykus",
"version": "0.7.5",
"version": "0.7.6",
"exports": "./src/build.ts",
"tasks": {
"build": "deno run -A src/build.ts --site_dir src/_site",
Expand Down
3 changes: 3 additions & 0 deletions src/_site/components/Error.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<script>
throw Error("Will not work");
</script>
4 changes: 4 additions & 0 deletions src/_site/components/errors/InvalidJavaScript.island.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<script lang="ts">
// this comment is fine,
but this is not actual code
</script>
3 changes: 3 additions & 0 deletions src/_site/components/errors/InvalidStyles.island.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<style>
this won’t work…
</style>
3 changes: 3 additions & 0 deletions src/_site/components/errors/Throw.island.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<scriiiiiiiiii

{throw "no can do"}
5 changes: 5 additions & 0 deletions src/_site/routes/error.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
import Error from "../components/Error.svelte";
</script>

<Error>This will never render</Error>
4 changes: 3 additions & 1 deletion src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,13 @@ export const rebuild = async ({
...baseESBuildConfig,
};

await Promise.all([
const results = await Promise.allSettled([
esbuild.build(routesESBuildConfig),
esbuild.build(islandsESBuildConfig),
copy_assets({ site_dir, out_dir }),
]);
const issues = results.filter(({ status }) => status === "rejected").length;
if (issues > 0) console.warn(`Encoutered ${issues} issues`);
};

export const build = async (
Expand Down
9 changes: 7 additions & 2 deletions src/esbuild_plugins/build_routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const build_routes: Plugin = {

const routes = result.outputFiles ?? [];

await Promise.all(routes.map(async (route) => {
await Promise.allSettled(routes.map(async (route) => {
const module = await import(
"data:application/javascript," + encodeURIComponent(route.text)
) as {
Expand Down Expand Up @@ -50,7 +50,12 @@ export const build_routes: Plugin = {
dist_path,
await get_route_html({ html, css, head: deduped_head }),
);
}));
})).then((results) => {
const { length } = results.filter(({ status }) =>
status === "rejected"
);
if (length > 0) console.log(`Failed to build ${length} routes.`);
});

console.log(
`Built ${routes.length} routes in ${
Expand Down
125 changes: 81 additions & 44 deletions src/esbuild_plugins/svelte_components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,29 @@ const SVELTE_IMPORTS = /(from|import) ['"](?:svelte)(\/?[\w\/-]*)['"]/g;
const specifiers = (code: string) =>
code.replaceAll(SVELTE_IMPORTS, `$1 'npm:svelte@${VERSION}$2'`);

/** From https://esbuild.github.io/plugins/#svelte-plugin */
const convertMessage = (
path: string,
source: string,
{ message, start, end }: ReturnType<typeof compile>["warnings"][number],
) => {
if (!start || !end) {
return { text: message };
}
const lineText = source.split(/\r\n|\r|\n/g)[start.line - 1];
const lineEnd = start.line === end.line ? end.column : lineText?.length ?? 0;
return {
text: message,
location: {
file: path,
line: start.line,
column: start.column,
length: lineEnd - start.column,
lineText,
},
};
};

export const svelte_components = (
site_dir: string,
base_path: string,
Expand Down Expand Up @@ -96,52 +119,66 @@ export const svelte_components = (
? OneClaw({ path, name, module_src })
: await Deno.readTextFile(path);

const { js: { code } } = compile(source, {
generate,
css: "external",
cssHash: ({ hash, css }) => `◖${hash(css)}◗`,
hydratable: generate === "dom",
enableSourcemap: false,
filename: basename(path),
});

if (generate === "dom" && path.endsWith(".island.svelte")) {
/** Dynamic function to be inlined in the output. */
const hydrator = (name: string, Component: ComponentType) => {
try {
document.querySelectorAll(
`one-claw[name='${name}']:not(one-claw one-claw)`,
).forEach((target) => {
const load = performance.now();
console.groupCollapsed(
`Hydrating %c${name}%c`,
"color: orange",
"color: reset",
);
console.log(target);
const props = JSON.parse(target.getAttribute("props") ?? "{}");
new Component({ target, props, hydrate: true });
console.log(
`Done in %c${
Math.round((performance.now() - load) * 1000) / 1000
}ms`,
"color: orange",
);
console.groupEnd();
});
} catch (error) {
console.error(error);
}
};

return ({
contents: `${
specifiers(code)
};(${hydrator.toString()})("${name}", ${name}_island)`,
try {
const { js: { code }, warnings } = compile(source, {
generate,
css: "external",
cssHash: ({ hash, css }) => `◖${hash(css)}◗`,
hydratable: generate === "dom",
enableSourcemap: false,
filename: basename(path),
});
}

return ({ contents: specifiers(code) });
if (generate === "dom" && path.endsWith(".island.svelte")) {
/** Dynamic function to be inlined in the output. */
const hydrator = (name: string, Component: ComponentType) => {
try {
document.querySelectorAll(
`one-claw[name='${name}']:not(one-claw one-claw)`,
).forEach((target) => {
const load = performance.now();
console.groupCollapsed(
`Hydrating %c${name}%c`,
"color: orange",
"color: reset",
);
console.log(target);
const props = JSON.parse(target.getAttribute("props") ?? "{}");
new Component({ target, props, hydrate: true });
console.log(
`Done in %c${
Math.round((performance.now() - load) * 1000) / 1000
}ms`,
"color: orange",
);
console.groupEnd();
});
} catch (error) {
console.error(error);
}
};

return ({
contents: `${
specifiers(code)
};(${hydrator.toString()})("${name}", ${name}_island)`,
warnings: warnings.map(
(warning) => convertMessage(path, source, warning),
),
});
}

return ({ contents: specifiers(code) });
} catch (error) {
return {
errors: [
convertMessage(path, source, {
message: String(error),
code: "???",
}),
],
};
}
});
},
});
Expand Down

0 comments on commit 749b3dd

Please sign in to comment.