diff --git a/src/functions/server/watcher.tsx b/src/functions/server/watcher.tsx index e84ad13..648ec9c 100644 --- a/src/functions/server/watcher.tsx +++ b/src/functions/server/watcher.tsx @@ -38,6 +38,8 @@ export default function watcher() { console.log(`Page ${action}: ${filename}. Rebuilding ...`); + global.ROUTER.reload(); + await global.BUNDLER_CTX?.dispose(); global.BUNDLER_CTX = undefined; diff --git a/src/functions/server/web-pages/grab-page-component.tsx b/src/functions/server/web-pages/grab-page-component.tsx index 981d814..5ea7842 100644 --- a/src/functions/server/web-pages/grab-page-component.tsx +++ b/src/functions/server/web-pages/grab-page-component.tsx @@ -1,15 +1,16 @@ import type { FC } from "react"; import grabDirNames from "../../../utils/grab-dir-names"; import grabRouteParams from "../../../utils/grab-route-params"; -import grabRouter from "../../../utils/grab-router"; import type { - BundlerCTXMap, BunextPageModule, + BunextPageModuleServerReturn, + BunxRouteParams, GrabPageComponentRes, } from "../../../types"; import path from "path"; import AppNames from "../../../utils/grab-app-names"; import { existsSync } from "fs"; +import grabPageErrorComponent from "./grab-page-error-component"; class NotFoundError extends Error {} @@ -23,20 +24,22 @@ export default async function grabPageComponent({ file_path: passed_file_path, }: Params): Promise { const url = req?.url ? new URL(req.url) : undefined; - const router = grabRouter(); + const router = global.ROUTER; - const { - BUNX_ROOT_500_PRESET_COMPONENT, - BUNX_ROOT_404_PRESET_COMPONENT, - PAGES_DIR, - } = grabDirNames(); + const { PAGES_DIR } = grabDirNames(); - const routeParams = req ? await grabRouteParams({ req }) : undefined; + let routeParams: BunxRouteParams | undefined = undefined; try { - const match = url ? router.match(url.pathname) : undefined; + routeParams = req ? await grabRouteParams({ req }) : undefined; - console.log("match", match); + let url_path = url ? url.pathname : undefined; + + if (url_path && url?.search) { + url_path += url.search; + } + + const match = url_path ? router.match(url_path) : undefined; if (!match?.filePath && url?.pathname) { throw new NotFoundError(`Page ${url.pathname} not found`); @@ -91,14 +94,22 @@ export default async function grabPageComponent({ const module: BunextPageModule = await import(`${file_path}?t=${now}`); - const serverRes = await (async () => { + const serverRes: BunextPageModuleServerReturn = await (async () => { try { if (routeParams) { - return await module["server"]?.(routeParams); + const serverData = await module["server"]?.(routeParams); + return { + ...serverData, + query: match?.query, + }; } - return {}; + return { + query: match?.query, + }; } catch (error) { - return {}; + return { + query: match?.query, + }; } })(); @@ -132,55 +143,10 @@ export default async function grabPageComponent({ meta, }; } catch (error: any) { - const is404 = error instanceof NotFoundError; - const errorRoute = is404 ? "/404" : "/500"; - const presetComponent = is404 - ? BUNX_ROOT_404_PRESET_COMPONENT - : BUNX_ROOT_500_PRESET_COMPONENT; - - try { - const match = router.match(errorRoute); - const filePath = match?.filePath || presetComponent; - - const bundledMap = match?.filePath - ? (global.BUNDLER_CTX_MAP?.find( - (m) => m.local_path === match.filePath, - ) ?? ({} as BundlerCTXMap)) - : ({} as BundlerCTXMap); - - const module: BunextPageModule = await import(filePath); - const Component = module.default as FC; - const component = ; - - return { - component, - routeParams, - module, - bundledMap, - }; - } catch { - const DefaultNotFound: FC = () => ( -
- - {is404 ? "404 Not Found" : "500 Internal Server Error"} - -
- ); - - return { - component: , - routeParams, - module: { default: DefaultNotFound }, - bundledMap: {} as BundlerCTXMap, - }; - } + return await grabPageErrorComponent({ + error, + routeParams, + is404: error instanceof NotFoundError, + }); } } diff --git a/src/functions/server/web-pages/grab-page-error-component.tsx b/src/functions/server/web-pages/grab-page-error-component.tsx new file mode 100644 index 0000000..d466af2 --- /dev/null +++ b/src/functions/server/web-pages/grab-page-error-component.tsx @@ -0,0 +1,75 @@ +import type { FC } from "react"; +import grabDirNames from "../../../utils/grab-dir-names"; +import type { + BundlerCTXMap, + BunextPageModule, + BunxRouteParams, + GrabPageComponentRes, +} from "../../../types"; + +type Params = { + error?: any; + routeParams?: BunxRouteParams; + is404?: boolean; +}; + +export default async function grabPageErrorComponent({ + error, + routeParams, + is404, +}: Params): Promise { + const router = global.ROUTER; + + const { BUNX_ROOT_500_PRESET_COMPONENT, BUNX_ROOT_404_PRESET_COMPONENT } = + grabDirNames(); + + const errorRoute = is404 ? "/404" : "/500"; + const presetComponent = is404 + ? BUNX_ROOT_404_PRESET_COMPONENT + : BUNX_ROOT_500_PRESET_COMPONENT; + + try { + const match = router.match(errorRoute); + const filePath = match?.filePath || presetComponent; + + const bundledMap = match?.filePath + ? (global.BUNDLER_CTX_MAP?.find( + (m) => m.local_path === match.filePath, + ) ?? ({} as BundlerCTXMap)) + : ({} as BundlerCTXMap); + + const module: BunextPageModule = await import(filePath); + const Component = module.default as FC; + const component = {{error.message}}; + + return { + component, + routeParams, + module, + bundledMap, + }; + } catch { + const DefaultNotFound: FC = () => ( +
+

{is404 ? "404 Not Found" : "500 Internal Server Error"}

+ {error.message} +
+ ); + + return { + component: , + routeParams, + module: { default: DefaultNotFound }, + bundledMap: {} as BundlerCTXMap, + }; + } +} diff --git a/src/functions/server/web-pages/handle-web-pages.tsx b/src/functions/server/web-pages/handle-web-pages.tsx index d9d657e..d9cb8b6 100644 --- a/src/functions/server/web-pages/handle-web-pages.tsx +++ b/src/functions/server/web-pages/handle-web-pages.tsx @@ -1,55 +1,59 @@ +import type { GrabPageComponentRes } from "../../../types"; import isDevelopment from "../../../utils/is-development"; import genWebHTML from "./generate-web-html"; import grabPageComponent from "./grab-page-component"; +import grabPageErrorComponent from "./grab-page-error-component"; type Params = { req: Request; }; -export default async function ({ req }: Params): Promise { +export default async function handleWebPages({ + req, +}: Params): Promise { try { - const { - component, - bundledMap, - module, - serverRes, - meta, - head, - routeParams, - } = await grabPageComponent({ req }); - - const html = await genWebHTML({ - component, - pageProps: serverRes, - bundledMap, - module, - meta, - head, - }); - - const res_opts: ResponseInit = { - headers: { - "Content-Type": "text/html", - }, - }; - - if (isDevelopment()) { - res_opts.headers = { - ...res_opts.headers, - "Cache-Control": "no-cache, no-store, must-revalidate", - Pragma: "no-cache", - Expires: "0", - }; - } - - const res = new Response(html, res_opts); - - return res; + const componentRes = await grabPageComponent({ req }); + return await generateRes(componentRes); } catch (error: any) { - console.log(`Handle web pages Error =>`, error.message); - - return new Response(error.message || `Page Not Found`, { - status: 404, - }); + const componentRes = await grabPageErrorComponent({ error }); + return await generateRes(componentRes); } } + +async function generateRes({ + component, + module, + bundledMap, + head, + meta, + routeParams, + serverRes, +}: GrabPageComponentRes) { + const html = await genWebHTML({ + component, + pageProps: serverRes, + bundledMap, + module, + meta, + head, + }); + + const res_opts: ResponseInit = { + headers: { + "Content-Type": "text/html", + }, + }; + + if (isDevelopment()) { + res_opts.headers = { + ...res_opts.headers, + "Cache-Control": "no-cache, no-store, must-revalidate", + Pragma: "no-cache", + Expires: "0", + }; + } + + const res = new Response(html, res_opts); + + return res; +} diff --git a/src/presets/not-found.tsx b/src/presets/not-found.tsx index 2119b4a..743348d 100644 --- a/src/presets/not-found.tsx +++ b/src/presets/not-found.tsx @@ -1,4 +1,6 @@ -export default function DefaultNotFoundPage() { +import type { PropsWithChildren } from "react"; + +export default function DefaultNotFoundPage({ children }: PropsWithChildren) { return (
- 404 Not Found +

404 Not Found

+ {children}
); } diff --git a/src/presets/server-error.tsx b/src/presets/server-error.tsx index b76dff8..25bfd37 100644 --- a/src/presets/server-error.tsx +++ b/src/presets/server-error.tsx @@ -1,4 +1,8 @@ -export default function DefaultServerErrorPage() { +import type { PropsWithChildren } from "react"; + +export default function DefaultServerErrorPage({ + children, +}: PropsWithChildren) { return (
- 500 Internal Server Error +

500 Internal Server Error

+ {children}
); } diff --git a/src/types/index.ts b/src/types/index.ts index dfa4fbf..0a32f77 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -176,8 +176,10 @@ export type BunextPageServerFn< export type BunextPageModuleServerReturn< T extends { [k: string]: any } = { [k: string]: any }, + Q extends { [k: string]: any } = { [k: string]: any }, > = { props?: T; + query?: Q; }; export type BunextPageModuleMetadata = { diff --git a/src/utils/grab-router.ts b/src/utils/grab-router.ts index 2d497de..8a36a04 100644 --- a/src/utils/grab-router.ts +++ b/src/utils/grab-router.ts @@ -1,14 +1,7 @@ -import grabDirNames from "./grab-dir-names"; - export default function grabRouter() { - const { PAGES_DIR } = grabDirNames(); + // if (process.env.NODE_ENV !== "production") { + // global.ROUTER.reload(); + // } - if (process.env.NODE_ENV == "production") { - return global.ROUTER; - } - - return new Bun.FileSystemRouter({ - style: "nextjs", - dir: PAGES_DIR, - }); + return global.ROUTER; }