diff --git a/src/entry-client.tsx b/src/entry-client.tsx index 2ca581c..40c2305 100644 --- a/src/entry-client.tsx +++ b/src/entry-client.tsx @@ -1,5 +1,30 @@ // @refresh reload import { injectSpeedInsights } from "@vercel/speed-insights"; import { mount, StartClient } from "@solidjs/start/client"; + +// Handle chunk loading failures from stale cache +window.addEventListener("error", (event) => { + if ( + event.message?.includes("Importing a module script failed") || + event.message?.includes("Failed to fetch dynamically imported module") + ) { + console.warn("Chunk load error detected, reloading page..."); + window.location.reload(); + } +}); + +window.addEventListener("unhandledrejection", (event) => { + if ( + event.reason?.message?.includes("Importing a module script failed") || + event.reason?.message?.includes( + "Failed to fetch dynamically imported module" + ) + ) { + console.warn("Chunk load error detected, reloading page..."); + event.preventDefault(); + window.location.reload(); + } +}); + injectSpeedInsights(); mount(() => , document.getElementById("app")!); diff --git a/src/routes/blog/create/index.tsx b/src/routes/blog/create/index.tsx index 848c24b..a89c69d 100644 --- a/src/routes/blog/create/index.tsx +++ b/src/routes/blog/create/index.tsx @@ -1,20 +1,29 @@ import { Show } from "solid-js"; -import { query } from "@solidjs/router"; +import { query, redirect } from "@solidjs/router"; import { Title, Meta } from "@solidjs/meta"; import { createAsync } from "@solidjs/router"; -import { getRequestEvent } from "solid-js/web"; +import { getEvent } from "vinxi/http"; import PostForm from "~/components/blog/PostForm"; import "../post.css"; const getAuthState = query(async () => { "use server"; const { getPrivilegeLevel, getUserID } = await import("~/server/utils"); - const event = getRequestEvent()!; - const privilegeLevel = await getPrivilegeLevel(event.nativeEvent); - const userID = await getUserID(event.nativeEvent); + const event = getEvent()!; + const privilegeLevel = await getPrivilegeLevel(event); + const userID = await getUserID(event); + + // Return 401 for non-admin users + if (privilegeLevel !== "admin") { + throw new Response("Unauthorized", { status: 401 }); + } return { privilegeLevel, userID }; -}, "auth-state"); +}, "create-post-auth"); + +export const route = { + load: () => getAuthState() +}; export default function CreatePost() { const authState = createAsync(() => getAuthState()); @@ -27,20 +36,8 @@ export default function CreatePost() { content="Create a new blog post with rich text editing, image uploads, and tag management." /> - -
Unauthorized
-
- You must be an admin to create posts. -
- - } - > - - - + + ); diff --git a/src/routes/blog/edit/[id].tsx b/src/routes/blog/edit/[id].tsx index f16bed0..306f444 100644 --- a/src/routes/blog/edit/[id].tsx +++ b/src/routes/blog/edit/[id].tsx @@ -2,7 +2,7 @@ import { Show } from "solid-js"; import { useParams, query } from "@solidjs/router"; import { Title, Meta } from "@solidjs/meta"; import { createAsync } from "@solidjs/router"; -import { getRequestEvent } from "solid-js/web"; +import { getEvent } from "vinxi/http"; import PostForm from "~/components/blog/PostForm"; import "../post.css"; @@ -10,9 +10,14 @@ const getPostForEdit = query(async (id: string) => { "use server"; const { getPrivilegeLevel, getUserID, ConnectionFactory } = await import("~/server/utils"); - const event = getRequestEvent()!; - const privilegeLevel = await getPrivilegeLevel(event.nativeEvent); - const userID = await getUserID(event.nativeEvent); + const event = getEvent()!; + const privilegeLevel = await getPrivilegeLevel(event); + const userID = await getUserID(event); + + // Return 401 for non-admin users + if (privilegeLevel !== "admin") { + throw new Response("Unauthorized", { status: 401 }); + } const conn = ConnectionFactory(); const query = `SELECT * FROM Post WHERE id = ?`; @@ -33,6 +38,10 @@ const getPostForEdit = query(async (id: string) => { return { post, tags, privilegeLevel, userID }; }, "post-for-edit"); +export const route = { + load: ({ params }: { params: { id: string } }) => getPostForEdit(params.id) +}; + export default function EditPost() { const params = useParams(); const data = createAsync(() => getPostForEdit(params.id)); @@ -64,31 +73,19 @@ export default function EditPost() { /> -
Unauthorized
-
- You must be an admin to edit posts. -
+
Loading post...
} > - -
Loading post...
- - } - > - -
+
); diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..bb66237 --- /dev/null +++ b/vercel.json @@ -0,0 +1,22 @@ +{ + "headers": [ + { + "source": "/(.*)", + "headers": [ + { + "key": "Cache-Control", + "value": "public, max-age=0, stale-while-revalidate=60" + } + ] + }, + { + "source": "/_build/(.*)", + "headers": [ + { + "key": "Cache-Control", + "value": "public, max-age=31536000, immutable" + } + ] + } + ] +}