From ee1fb5897ed37cdec372f27b1dfc71595bc989aa Mon Sep 17 00:00:00 2001
From: Benjamin Toby
Date: Tue, 17 Mar 2026 18:53:27 +0100
Subject: [PATCH] Add More Features to pages main component
---
src/functions/bundler/all-pages-bundler.ts | 153 +-----------------
.../server/web-pages/generate-web-html.tsx | 7 +-
.../server/web-pages/grab-page-component.tsx | 2 +
.../server/web-pages/handle-web-pages.tsx | 16 ++
src/types/index.ts | 27 +++-
5 files changed, 52 insertions(+), 153 deletions(-)
diff --git a/src/functions/bundler/all-pages-bundler.ts b/src/functions/bundler/all-pages-bundler.ts
index 1c0ee12..1345b9d 100644
--- a/src/functions/bundler/all-pages-bundler.ts
+++ b/src/functions/bundler/all-pages-bundler.ts
@@ -141,27 +141,18 @@ export default async function allPagesBundler(params?: Params) {
const final_artifacts = artifacts.filter((a) =>
Boolean(a?.entrypoint),
) as BundlerCTXMap[];
- // writeFileSync(
- // HYDRATION_DST_DIR_MAP_JSON_FILE,
- // JSON.stringify(final_artifacts),
- // );
-
global.BUNDLER_CTX_MAP = final_artifacts;
params?.post_build_fn?.({ artifacts: final_artifacts });
+
+ writeFileSync(
+ HYDRATION_DST_DIR_MAP_JSON_FILE,
+ JSON.stringify(artifacts),
+ );
}
console.timeEnd("build");
- writeFileSync(
- HYDRATION_DST_DIR_MAP_JSON_FILE,
- JSON.stringify(artifacts),
- );
-
if (params?.exit_after_first_build) {
- // console.log(
- // "global.BUNDLER_CTX_MAP",
- // global.BUNDLER_CTX_MAP,
- // );
process.exit();
}
});
@@ -184,7 +175,6 @@ export default async function allPagesBundler(params?: Params) {
),
},
entryNames: "[dir]/[name]/[hash]",
- // entryNames: "[name]/[hash]",
metafile: true,
plugins: [tailwindPlugin, virtualPlugin, artifactTracker],
jsx: "automatic",
@@ -197,136 +187,3 @@ export default async function allPagesBundler(params?: Params) {
global.BUNDLER_CTX.watch();
}
}
-
-// import plugin from "bun-plugin-tailwind";
-// import { readdirSync, statSync, unlinkSync, writeFileSync } from "fs";
-// import grabAllPages from "../../utils/grab-all-pages";
-// import grabDirNames from "../../utils/grab-dir-names";
-// import grabPageName from "../../utils/grab-page-name";
-// import writeWebPageHydrationScript from "../server/web-pages/write-web-page-hydration-script";
-// import path from "path";
-// import bundle from "../../utils/bundle";
-// import AppNames from "../../utils/grab-app-names";
-// import type { PageFiles } from "../../types";
-// import isDevelopment from "../../utils/is-development";
-// import { execSync } from "child_process";
-
-// const {
-// BUNX_HYDRATION_SRC_DIR,
-// HYDRATION_DST_DIR,
-// HYDRATION_DST_DIR_MAP_JSON_FILE,
-// } = grabDirNames();
-
-// export default async function allPagesBundler() {
-// console.time("build");
-
-// const pages = grabAllPages({ exclude_api: true });
-
-// for (let i = 0; i < pages.length; i++) {
-// const page = pages[i];
-
-// if (!isPageValid(page)) {
-// continue;
-// }
-
-// const pageName = grabPageName({ path: page.local_path });
-
-// writeWebPageHydrationScript({
-// pageName,
-// page_file: page.local_path,
-// });
-// }
-
-// // const hydration_files = readdirSync(BUNX_HYDRATION_SRC_DIR);
-
-// // for (let i = 0; i < hydration_files.length; i++) {
-// // const hydration_file = hydration_files[i];
-
-// // const valid_file = pages.find((p) => {
-// // if (!isPageValid(p)) {
-// // return false;
-// // }
-
-// // const pageName = grabPageName({ path: p.local_path });
-
-// // const file_tsx_name = `${pageName}.tsx`;
-// // if (file_tsx_name == hydration_file) {
-// // return true;
-// // }
-// // return false;
-// // });
-
-// // if (!valid_file) {
-// // unlinkSync(path.join(BUNX_HYDRATION_SRC_DIR, hydration_file));
-// // }
-// // }
-
-// // const entrypoints = readdirSync(BUNX_HYDRATION_SRC_DIR)
-// // .filter((f) => f.endsWith(".tsx"))
-// // .map((f) => path.join(BUNX_HYDRATION_SRC_DIR, f))
-// // .filter((f) => statSync(f).isFile());
-
-// const entrypoints = pages.map((p) => p.local_path);
-
-// // execSync(`rm -rf ${HYDRATION_DST_DIR}`);
-
-// // bundle({
-// // src: entrypoints.join(" "),
-// // out_dir: HYDRATION_DST_DIR,
-// // exec_options: { stdio: "ignore" },
-// // entry_naming: `[dir]/[name]/[hash].js`,
-// // minify: true,
-// // target: "browser",
-// // });
-
-// // console.log(`Bundling ...`);
-
-// const result = await Bun.build({
-// entrypoints,
-// outdir: HYDRATION_DST_DIR,
-// plugins: [plugin],
-// minify: true,
-// target: "browser",
-// // sourcemap: "linked",
-// define: {
-// "process.env.NODE_ENV": JSON.stringify(
-// isDevelopment() ? "development" : "production",
-// ),
-// },
-// naming: "[dir]/[name]/[hash].js",
-// });
-
-// const artifacts = result.outputs.map(({ path, hash, type }) => {
-// const target_page = pages.find((p) =>
-// p.local_path.replace(/src\/pages/, "public/pages"),
-// );
-
-// return {
-// path,
-// hash,
-// type,
-// ...target_page,
-// };
-// });
-
-// if (artifacts?.[0]) {
-// writeFileSync(
-// HYDRATION_DST_DIR_MAP_JSON_FILE,
-// JSON.stringify(artifacts),
-// );
-// }
-
-// console.timeEnd("build");
-// }
-
-// function isPageValid(page: PageFiles): boolean {
-// if (page.file_name == AppNames["RootPagesComponentName"]) {
-// return false;
-// }
-
-// if (page.url_path.match(/\(|\)|--/)) {
-// return false;
-// }
-
-// return true;
-// }
diff --git a/src/functions/server/web-pages/generate-web-html.tsx b/src/functions/server/web-pages/generate-web-html.tsx
index 3a581f5..1777c7a 100644
--- a/src/functions/server/web-pages/generate-web-html.tsx
+++ b/src/functions/server/web-pages/generate-web-html.tsx
@@ -10,9 +10,10 @@ export default async function genWebHTML({
component,
pageProps,
bundledMap,
- head,
+ head: Head,
module,
meta,
+ routeParams,
}: LivePageDistGenParams) {
const { ClientRootElementIDName, ClientWindowPagePropsName } =
await grabContants();
@@ -22,7 +23,9 @@ export default async function genWebHTML({
);
const componentHTML = renderToString(component);
- const headHTML = head ? renderToString(head) : "";
+ const headHTML = Head
+ ? renderToString()
+ : "";
let html = `\n`;
html += `\n`;
diff --git a/src/functions/server/web-pages/grab-page-component.tsx b/src/functions/server/web-pages/grab-page-component.tsx
index 5ea7842..f0a2047 100644
--- a/src/functions/server/web-pages/grab-page-component.tsx
+++ b/src/functions/server/web-pages/grab-page-component.tsx
@@ -125,6 +125,7 @@ export default async function grabPageComponent({
: undefined;
const Component = module.default as FC;
+ const Head = module.head as FC;
const component = RootComponent ? (
@@ -141,6 +142,7 @@ export default async function grabPageComponent({
module,
bundledMap,
meta,
+ head: Head,
};
} catch (error: any) {
return await grabPageErrorComponent({
diff --git a/src/functions/server/web-pages/handle-web-pages.tsx b/src/functions/server/web-pages/handle-web-pages.tsx
index d9cb8b6..cb0b741 100644
--- a/src/functions/server/web-pages/handle-web-pages.tsx
+++ b/src/functions/server/web-pages/handle-web-pages.tsx
@@ -36,11 +36,23 @@ async function generateRes({
module,
meta,
head,
+ routeParams,
});
+ if (serverRes?.redirect?.destination) {
+ return Response.redirect(
+ serverRes.redirect.destination,
+ serverRes.redirect.permanent
+ ? 301
+ : serverRes.redirect.status_code || 302,
+ );
+ }
+
const res_opts: ResponseInit = {
+ ...serverRes?.responseOptions,
headers: {
"Content-Type": "text/html",
+ ...serverRes?.responseOptions?.headers,
},
};
@@ -55,5 +67,9 @@ async function generateRes({
const res = new Response(html, res_opts);
+ if (routeParams?.resTransform) {
+ return await routeParams.resTransform(res);
+ }
+
return res;
}
diff --git a/src/types/index.ts b/src/types/index.ts
index 0a32f77..bdc22ee 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -65,6 +65,10 @@ export type BunxRouteParams = {
url: URL;
body?: any;
query?: any;
+ /**
+ * Intercept and Transform the response object
+ */
+ resTransform?: (res: Response) => Promise | Response;
};
export interface PostInsertReturn {
@@ -125,17 +129,24 @@ export type PageDistGenParams = {
export type LivePageDistGenParams = {
component: ReactNode;
- head?: ReactNode;
+ head?: FC;
pageProps?: any;
module?: BunextPageModule;
bundledMap?: BundlerCTXMap;
meta?: BunextPageModuleMeta;
+ routeParams?: BunxRouteParams;
+};
+
+export type BunextPageHeadFCProps = {
+ serverRes: BunextPageModuleServerReturn;
+ ctx?: BunxRouteParams;
};
export type BunextPageModule = {
default: FC;
server?: BunextPageServerFn;
meta?: BunextPageModuleMeta | BunextPageModuleMetaFn;
+ head?: FC;
};
export type BunextPageModuleMetaFn = (params: {
@@ -172,7 +183,9 @@ export type BunextPageModuleMeta = {
export type BunextPageServerFn<
T extends { [k: string]: any } = { [k: string]: any },
-> = (routeParams: BunxRouteParams) => Promise>;
+> = (
+ ctx: Omit,
+) => Promise>;
export type BunextPageModuleServerReturn<
T extends { [k: string]: any } = { [k: string]: any },
@@ -180,6 +193,14 @@ export type BunextPageModuleServerReturn<
> = {
props?: T;
query?: Q;
+ redirect?: BunextPageModuleServerRedirect;
+ responseOptions?: ResponseInit;
+};
+
+export type BunextPageModuleServerRedirect = {
+ destination: string;
+ permanent?: boolean;
+ status_code?: number;
};
export type BunextPageModuleMetadata = {
@@ -194,7 +215,7 @@ export type GrabPageComponentRes = {
bundledMap?: BundlerCTXMap;
module: BunextPageModule;
meta?: BunextPageModuleMeta;
- head?: ReactNode;
+ head?: FC;
};
export type PageFiles = {