From 6f1db7c01f52183487c2f538ff101f9892ee4276 Mon Sep 17 00:00:00 2001
From: Benjamin Toby
Date: Mon, 23 Mar 2026 19:14:56 +0100
Subject: [PATCH] Add more features. Customize HTML. Add server logic and other
page module exports to __root
---
.../bundler/all-pages-bun-bundler.ts | 5 +-
.../bundler/grab-client-hydration-script.tsx | 19 ++-
src/functions/bundler/record-artifacts.ts | 9 +-
src/functions/server/watcher.ts | 4 +-
.../server/web-pages/generate-web-html.tsx | 151 ++++++++++++------
...eb-page-response-from-component-return.tsx | 6 +-
.../server/web-pages/grab-page-component.tsx | 75 ++++-----
.../grab-page-react-component-string.tsx | 10 +-
.../server/web-pages/grab-page-server-res.tsx | 63 ++++++++
.../web-pages/grab-tsx-string-module.tsx | 56 +++++--
.../server/web-pages/grab-web-meta-html.ts | 77 ---------
.../server/web-pages/grab-web-meta-html.tsx | 76 +++++++++
src/presets/components/head.tsx | 13 ++
src/types/index.ts | 23 ++-
src/utils/rewrite-pages-module.ts | 34 ++--
15 files changed, 389 insertions(+), 232 deletions(-)
create mode 100644 src/functions/server/web-pages/grab-page-server-res.tsx
delete mode 100644 src/functions/server/web-pages/grab-web-meta-html.ts
create mode 100644 src/functions/server/web-pages/grab-web-meta-html.tsx
create mode 100644 src/presets/components/head.tsx
diff --git a/src/functions/bundler/all-pages-bun-bundler.ts b/src/functions/bundler/all-pages-bun-bundler.ts
index 3725b67..33530b5 100644
--- a/src/functions/bundler/all-pages-bun-bundler.ts
+++ b/src/functions/bundler/all-pages-bun-bundler.ts
@@ -124,7 +124,10 @@ export default async function allPagesBunBundler(params?: Params) {
}
if (artifacts?.[0]) {
- await recordArtifacts({ artifacts });
+ await recordArtifacts({
+ artifacts,
+ page_file_paths,
+ });
}
const elapsed = (performance.now() - buildStart).toFixed(0);
diff --git a/src/functions/bundler/grab-client-hydration-script.tsx b/src/functions/bundler/grab-client-hydration-script.tsx
index b297e54..6317089 100644
--- a/src/functions/bundler/grab-client-hydration-script.tsx
+++ b/src/functions/bundler/grab-client-hydration-script.tsx
@@ -4,6 +4,7 @@ import grabDirNames from "../../utils/grab-dir-names";
import AppNames from "../../utils/grab-app-names";
import grabConstants from "../../utils/grab-constants";
import pagePathTransform from "../../utils/page-path-transform";
+import grabRootFilePath from "../server/web-pages/grab-root-file-path";
const { PAGES_DIR } = grabDirNames();
@@ -20,25 +21,23 @@ export default async function grabClientHydrationScript({
ClientWindowPagePropsName,
} = grabConstants();
+ const { root_file_path } = grabRootFilePath();
+
const target_path = pagePathTransform({ page_path: page_local_path });
-
- const root_component_path = path.join(
- PAGES_DIR,
- `${AppNames["RootPagesComponentName"]}.tsx`,
- );
-
- const does_root_exist = existsSync(root_component_path);
+ const target_root_path = root_file_path
+ ? pagePathTransform({ page_path: root_file_path })
+ : undefined;
let txt = ``;
txt += `import { hydrateRoot } from "react-dom/client";\n`;
- if (does_root_exist) {
- txt += `import Root from "${root_component_path}";\n`;
+ if (target_root_path) {
+ txt += `import Root from "${target_root_path}";\n`;
}
txt += `import Page from "${target_path}";\n\n`;
txt += `const pageProps = window.${ClientWindowPagePropsName} || {};\n`;
- if (does_root_exist) {
+ if (target_root_path) {
txt += `const component = \n`;
} else {
txt += `const component = \n`;
diff --git a/src/functions/bundler/record-artifacts.ts b/src/functions/bundler/record-artifacts.ts
index 6736cf4..668e2a8 100644
--- a/src/functions/bundler/record-artifacts.ts
+++ b/src/functions/bundler/record-artifacts.ts
@@ -1,13 +1,18 @@
import grabDirNames from "../../utils/grab-dir-names";
import type { BundlerCTXMap } from "../../types";
+import _ from "lodash";
const { HYDRATION_DST_DIR_MAP_JSON_FILE } = grabDirNames();
type Params = {
artifacts: BundlerCTXMap[];
+ page_file_paths?: string[];
};
-export default async function recordArtifacts({ artifacts }: Params) {
+export default async function recordArtifacts({
+ artifacts,
+ page_file_paths,
+}: Params) {
const artifacts_map: { [k: string]: BundlerCTXMap } = {};
for (const artifact of artifacts) {
@@ -17,7 +22,7 @@ export default async function recordArtifacts({ artifacts }: Params) {
}
if (global.BUNDLER_CTX_MAP) {
- global.BUNDLER_CTX_MAP = artifacts_map;
+ global.BUNDLER_CTX_MAP = _.merge(global.BUNDLER_CTX_MAP, artifacts_map);
}
await Bun.write(
diff --git a/src/functions/server/watcher.ts b/src/functions/server/watcher.ts
index 8bcec42..63cd86b 100644
--- a/src/functions/server/watcher.ts
+++ b/src/functions/server/watcher.ts
@@ -86,9 +86,7 @@ async function fullRebuild(params?: { msg?: string }) {
(hmr) => hmr.target_map?.local_path,
).filter((f) => typeof f == "string");
- await rewritePagesModule({
- page_file_path: target_file_paths,
- });
+ await rewritePagesModule();
if (msg) {
log.watch(msg);
diff --git a/src/functions/server/web-pages/generate-web-html.tsx b/src/functions/server/web-pages/generate-web-html.tsx
index eba911a..ad1fe5e 100644
--- a/src/functions/server/web-pages/generate-web-html.tsx
+++ b/src/functions/server/web-pages/generate-web-html.tsx
@@ -24,78 +24,123 @@ export default async function genWebHTML({
component,
pageProps,
bundledMap,
- head: Head,
module,
- meta,
routeParams,
debug,
+ root_module,
}: LivePageDistGenParams) {
const { ClientRootElementIDName, ClientWindowPagePropsName } =
grabContants();
+ const is_dev = isDevelopment();
+
if (debug) {
log.info("component", component);
}
- const componentHTML = renderToString(component);
-
- if (debug) {
- log.info("componentHTML", componentHTML);
- }
-
- const headHTML = Head
- ? renderToString()
- : "";
-
- let html = `\n`;
- html += `\n`;
- html += `
\n`;
- html += ` \n`;
- html += ` \n`;
-
- if (meta) {
- html += ` ${grabWebMetaHTML({ meta })}\n`;
- }
-
- if (bundledMap?.css_path) {
- html += ` \n`;
- }
-
const serializedProps = (EJSON.stringify(pageProps || {}) || "{}").replace(
/<\//g,
"<\\/",
);
- html += ` \n`;
- if (bundledMap?.path) {
- const dev = isDevelopment();
- const devSuffix = dev ? "?dev" : "";
- const importMap = JSON.stringify({
- imports: {
- react: `https://esm.sh/react@${_reactVersion}${devSuffix}`,
- "react-dom": `https://esm.sh/react-dom@${_reactVersion}${devSuffix}`,
- "react-dom/client": `https://esm.sh/react-dom@${_reactVersion}/client${devSuffix}`,
- "react/jsx-runtime": `https://esm.sh/react@${_reactVersion}/jsx-runtime${devSuffix}`,
- "react/jsx-dev-runtime": `https://esm.sh/react@${_reactVersion}/jsx-dev-runtime${devSuffix}`,
- },
- });
- html += ` \n`;
- html += ` \n`;
- }
+ const page_hydration_script = await grabWebPageHydrationScript();
+ const root_meta = root_module?.meta
+ ? typeof root_module.meta == "function" && routeParams
+ ? await root_module.meta({ ctx: routeParams, serverRes: pageProps })
+ : typeof root_module.meta == "function"
+ ? undefined
+ : root_module.meta
+ : undefined;
+ const page_meta = module?.meta
+ ? typeof module.meta == "function" && routeParams
+ ? await module.meta({ ctx: routeParams, serverRes: pageProps })
+ : typeof module.meta == "function"
+ ? undefined
+ : module.meta
+ : undefined;
- if (isDevelopment()) {
- html += `\n`;
- }
+ const html_props = {
+ ...module?.html_props,
+ ...root_module?.html_props,
+ };
- if (headHTML) {
- html += ` ${headHTML}\n`;
- }
+ const Head = module?.Head;
+ const RootHead = root_module?.Head;
- html += ` \n`;
- html += ` \n`;
- html += ` ${componentHTML}
\n`;
- html += ` \n`;
- html += `\n`;
+ const dev = isDevelopment();
+ const devSuffix = dev ? "?dev" : "";
+ const importMap = JSON.stringify({
+ imports: {
+ react: `https://esm.sh/react@${_reactVersion}${devSuffix}`,
+ "react-dom": `https://esm.sh/react-dom@${_reactVersion}${devSuffix}`,
+ "react-dom/client": `https://esm.sh/react-dom@${_reactVersion}/client${devSuffix}`,
+ "react/jsx-runtime": `https://esm.sh/react@${_reactVersion}/jsx-runtime${devSuffix}`,
+ "react/jsx-dev-runtime": `https://esm.sh/react@${_reactVersion}/jsx-dev-runtime${devSuffix}`,
+ },
+ });
+
+ let final_component = (
+
+
+
+
+
+ {root_meta ? grabWebMetaHTML({ meta: root_meta }) : null}
+ {page_meta ? grabWebMetaHTML({ meta: page_meta }) : null}
+
+ {bundledMap?.css_path ? (
+
+ ) : null}
+
+
+
+ {bundledMap?.path ? (
+ <>
+
+
+ >
+ ) : null}
+
+ {is_dev ? (
+
+ ) : null}
+
+ {RootHead ? (
+
+ ) : null}
+ {Head ?
+ {component}
+
+
+ );
+
+ let html = `\n`;
+ html += renderToString(final_component);
return html;
}
diff --git a/src/functions/server/web-pages/generate-web-page-response-from-component-return.tsx b/src/functions/server/web-pages/generate-web-page-response-from-component-return.tsx
index cb810e4..0cf649d 100644
--- a/src/functions/server/web-pages/generate-web-page-response-from-component-return.tsx
+++ b/src/functions/server/web-pages/generate-web-page-response-from-component-return.tsx
@@ -8,21 +8,19 @@ export default async function generateWebPageResponseFromComponentReturn({
component,
module,
bundledMap,
- head,
- meta,
routeParams,
serverRes,
debug,
+ root_module,
}: GrabPageComponentRes) {
const html = await genWebHTML({
component,
pageProps: serverRes,
bundledMap,
module,
- meta,
- head,
routeParams,
debug,
+ root_module,
});
if (debug) {
diff --git a/src/functions/server/web-pages/grab-page-component.tsx b/src/functions/server/web-pages/grab-page-component.tsx
index 805f333..1560dea 100644
--- a/src/functions/server/web-pages/grab-page-component.tsx
+++ b/src/functions/server/web-pages/grab-page-component.tsx
@@ -1,8 +1,8 @@
-import type { FC } from "react";
import grabRouteParams from "../../../utils/grab-route-params";
import type {
BunextPageModule,
BunextPageModuleServerReturn,
+ BunextRootModule,
BunxRouteParams,
GrabPageComponentRes,
} from "../../../types";
@@ -11,6 +11,7 @@ import grabPageBundledReactComponent from "./grab-page-bundled-react-component";
import _ from "lodash";
import { log } from "../../../utils/log";
import grabRootFilePath from "./grab-root-file-path";
+import grabPageServerRes from "./grab-page-server-res";
class NotFoundError extends Error {}
@@ -65,6 +66,7 @@ export default async function grabPageComponent({
const bundledMap = global.BUNDLER_CTX_MAP?.[file_path];
if (!bundledMap?.path) {
+ console.log(global.BUNDLER_CTX_MAP);
const errMsg = `No Bundled File Path for this request path!`;
log.error(errMsg);
throw new Error(errMsg);
@@ -77,52 +79,36 @@ export default async function grabPageComponent({
const { root_file_path } = grabRootFilePath();
const module: BunextPageModule = await import(`${file_path}?t=${now}`);
+ const root_module: BunextRootModule | undefined = root_file_path
+ ? await import(`${root_file_path}?t=${now}`)
+ : undefined;
if (debug) {
log.info(`module:`, module);
}
- const serverRes: BunextPageModuleServerReturn = await (async () => {
- const default_props: BunextPageModuleServerReturn = {
- url: {
- ...(_.pick(url!, [
- "host",
- "hostname",
- "pathname",
- "origin",
- "port",
- "search",
- "searchParams",
- "hash",
- "href",
- "password",
- "protocol",
- "username",
- ]) as any),
- },
- query: match?.query,
- };
+ const rootServerRes: BunextPageModuleServerReturn | undefined =
+ root_module?.server
+ ? await grabPageServerRes({
+ module: root_module,
+ url,
+ query: match?.query,
+ routeParams,
+ })
+ : undefined;
- try {
- if (routeParams) {
- const serverData = await module["server"]?.({
- ...routeParams,
- query: { ...routeParams.query, ...match?.query },
- });
- return {
- ...serverData,
- ...default_props,
- };
- }
- return {
- ...default_props,
- };
- } catch (error) {
- return {
- ...default_props,
- };
- }
- })();
+ if (debug) {
+ log.info(`rootServerRes:`, rootServerRes);
+ }
+
+ const serverRes: BunextPageModuleServerReturn = await grabPageServerRes(
+ {
+ module,
+ url,
+ query: match?.query,
+ routeParams,
+ },
+ );
if (debug) {
log.info(`serverRes:`, serverRes);
@@ -143,8 +129,6 @@ export default async function grabPageComponent({
log.info(`meta:`, meta);
}
- const Head = module.Head as FC;
-
const { component } =
(await grabPageBundledReactComponent({
file_path,
@@ -162,12 +146,11 @@ export default async function grabPageComponent({
return {
component,
- serverRes,
+ serverRes: _.merge(rootServerRes || {}, serverRes),
routeParams,
module,
bundledMap,
- meta,
- head: Head,
+ root_module,
};
} catch (error: any) {
log.error(`Error Grabbing Page Component: ${error.message}`);
diff --git a/src/functions/server/web-pages/grab-page-react-component-string.tsx b/src/functions/server/web-pages/grab-page-react-component-string.tsx
index cbe6302..86b3616 100644
--- a/src/functions/server/web-pages/grab-page-react-component-string.tsx
+++ b/src/functions/server/web-pages/grab-page-react-component-string.tsx
@@ -14,21 +14,25 @@ export default function grabPageReactComponentString({
}: Params): string | undefined {
try {
const target_path = pagePathTransform({ page_path: file_path });
+ const target_root_path = root_file_path
+ ? pagePathTransform({ page_path: root_file_path })
+ : undefined;
+
let tsx = ``;
const server_res_json = JSON.stringify(
EJSON.stringify(server_res || {}) ?? "{}",
);
- if (root_file_path) {
- tsx += `import Root from "${root_file_path}"\n`;
+ if (target_root_path) {
+ tsx += `import Root from "${target_root_path}"\n`;
}
tsx += `import Page from "${target_path}"\n`;
tsx += `export default function Main() {\n\n`;
tsx += `const props = JSON.parse(${server_res_json})\n\n`;
tsx += ` return (\n`;
- if (root_file_path) {
+ if (target_root_path) {
tsx += ` \n`;
} else {
tsx += ` \n`;
diff --git a/src/functions/server/web-pages/grab-page-server-res.tsx b/src/functions/server/web-pages/grab-page-server-res.tsx
new file mode 100644
index 0000000..d64de3a
--- /dev/null
+++ b/src/functions/server/web-pages/grab-page-server-res.tsx
@@ -0,0 +1,63 @@
+import type {
+ BunextPageModule,
+ BunextPageModuleServerReturn,
+ BunxRouteParams,
+ GrabPageComponentRes,
+} from "../../../types";
+import _ from "lodash";
+
+type Params = {
+ url?: URL;
+ module: BunextPageModule;
+ query?: Record;
+ routeParams?: BunxRouteParams;
+};
+
+export default async function grabPageServerRes({
+ url,
+ query,
+ routeParams,
+ module,
+}: Params): Promise {
+ const default_props: BunextPageModuleServerReturn = {
+ url: url
+ ? {
+ ...(_.pick(url, [
+ "host",
+ "hostname",
+ "pathname",
+ "origin",
+ "port",
+ "search",
+ "searchParams",
+ "hash",
+ "href",
+ "password",
+ "protocol",
+ "username",
+ ]) as any),
+ }
+ : null,
+ query,
+ };
+
+ try {
+ if (routeParams) {
+ const serverData = await module["server"]?.({
+ ...routeParams,
+ query: { ...routeParams.query, ...query },
+ });
+ return {
+ ...serverData,
+ ...default_props,
+ };
+ }
+ return {
+ ...default_props,
+ };
+ } catch (error) {
+ return {
+ ...default_props,
+ };
+ }
+}
diff --git a/src/functions/server/web-pages/grab-tsx-string-module.tsx b/src/functions/server/web-pages/grab-tsx-string-module.tsx
index d161598..497e938 100644
--- a/src/functions/server/web-pages/grab-tsx-string-module.tsx
+++ b/src/functions/server/web-pages/grab-tsx-string-module.tsx
@@ -1,8 +1,7 @@
import isDevelopment from "../../../utils/is-development";
-import * as esbuild from "esbuild";
+import tailwindcss from "bun-plugin-tailwind";
import grabDirNames from "../../../utils/grab-dir-names";
import path from "path";
-import tailwindEsbuildPlugin from "./tailwind-esbuild-plugin";
type Params = {
tsx: string;
@@ -20,21 +19,22 @@ export default async function grabTsxStringModule({
.replace(/.*\/src\/pages\//, "")
.replace(/\.tsx$/, "");
+ const src_file_path = path.join(
+ BUNX_CWD_MODULE_CACHE_DIR,
+ `${trimmed_file_path}.tsx`,
+ );
+
const out_file_path = path.join(
BUNX_CWD_MODULE_CACHE_DIR,
`${trimmed_file_path}.js`,
);
- await esbuild.build({
- stdin: {
- contents: tsx,
- resolveDir: process.cwd(),
- loader: "tsx",
- },
- bundle: true,
+ await Bun.write(src_file_path, tsx);
+
+ await Bun.build({
+ entrypoints: [src_file_path],
format: "esm",
- target: "es2020",
- platform: "node",
+ target: "bun",
external: ["react", "react-dom"],
minify: true,
define: {
@@ -43,10 +43,12 @@ export default async function grabTsxStringModule({
),
},
metafile: true,
- plugins: [tailwindEsbuildPlugin],
- jsx: "automatic",
- write: true,
- outfile: out_file_path,
+ plugins: [tailwindcss],
+ jsx: {
+ runtime: "automatic",
+ development: dev,
+ },
+ outdir: BUNX_CWD_MODULE_CACHE_DIR,
});
Loader.registry.delete(out_file_path);
@@ -54,3 +56,27 @@ export default async function grabTsxStringModule({
return module as T;
}
+
+// await esbuild.build({
+// stdin: {
+// contents: tsx,
+// resolveDir: process.cwd(),
+// loader: "tsx",
+// },
+// bundle: true,
+// format: "esm",
+// target: "es2020",
+// platform: "node",
+// external: ["react", "react-dom"],
+// minify: true,
+// define: {
+// "process.env.NODE_ENV": JSON.stringify(
+// dev ? "development" : "production",
+// ),
+// },
+// metafile: true,
+// plugins: [tailwindEsbuildPlugin],
+// jsx: "automatic",
+// write: true,
+// outfile: out_file_path,
+// });
diff --git a/src/functions/server/web-pages/grab-web-meta-html.ts b/src/functions/server/web-pages/grab-web-meta-html.ts
deleted file mode 100644
index 6eae617..0000000
--- a/src/functions/server/web-pages/grab-web-meta-html.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import { escape } from "lodash";
-import type { BunextPageModuleMeta } from "../../../types";
-
-type Params = {
- meta: BunextPageModuleMeta;
-};
-
-export default function grabWebMetaHTML({ meta }: Params) {
- let html = ``;
-
- if (meta.title) {
- html += ` ${escape(meta.title)}\n`;
- }
-
- if (meta.description) {
- html += ` \n`;
- }
-
- if (meta.keywords) {
- const keywords = Array.isArray(meta.keywords)
- ? meta.keywords.join(", ")
- : meta.keywords;
- html += ` \n`;
- }
-
- if (meta.author) {
- html += ` \n`;
- }
-
- if (meta.robots) {
- html += ` \n`;
- }
-
- if (meta.canonical) {
- html += ` \n`;
- }
-
- if (meta.themeColor) {
- html += ` \n`;
- }
-
- if (meta.og) {
- const { og } = meta;
- if (og.title)
- html += ` \n`;
- if (og.description)
- html += ` \n`;
- if (og.image)
- html += ` \n`;
- if (og.url)
- html += ` \n`;
- if (og.type)
- html += ` \n`;
- if (og.siteName)
- html += ` \n`;
- if (og.locale)
- html += ` \n`;
- }
-
- if (meta.twitter) {
- const { twitter } = meta;
- if (twitter.card)
- html += ` \n`;
- if (twitter.title)
- html += ` \n`;
- if (twitter.description)
- html += ` \n`;
- if (twitter.image)
- html += ` \n`;
- if (twitter.site)
- html += ` \n`;
- if (twitter.creator)
- html += ` \n`;
- }
-
- return html;
-}
diff --git a/src/functions/server/web-pages/grab-web-meta-html.tsx b/src/functions/server/web-pages/grab-web-meta-html.tsx
new file mode 100644
index 0000000..70191e3
--- /dev/null
+++ b/src/functions/server/web-pages/grab-web-meta-html.tsx
@@ -0,0 +1,76 @@
+import type { BunextPageModuleMeta } from "../../../types";
+
+type Params = {
+ meta: BunextPageModuleMeta;
+};
+
+export default function grabWebMetaHTML({ meta }: Params) {
+ const keywords = meta.keywords
+ ? Array.isArray(meta.keywords)
+ ? meta.keywords.join(", ")
+ : meta.keywords
+ : undefined;
+
+ return (
+ <>
+ {meta.title && {meta.title}}
+ {meta.description && (
+
+ )}
+ {keywords && }
+ {meta.author && }
+ {meta.robots && }
+ {meta.canonical && (
+
+ )}
+ {meta.themeColor && (
+
+ )}
+ {meta.og?.title && (
+
+ )}
+ {meta.og?.description && (
+
+ )}
+ {meta.og?.image && (
+
+ )}
+ {meta.og?.url && (
+
+ )}
+ {meta.og?.type && (
+
+ )}
+ {meta.og?.siteName && (
+
+ )}
+ {meta.og?.locale && (
+
+ )}
+ {meta.twitter?.card && (
+
+ )}
+ {meta.twitter?.title && (
+
+ )}
+ {meta.twitter?.description && (
+
+ )}
+ {meta.twitter?.image && (
+
+ )}
+ {meta.twitter?.site && (
+
+ )}
+ {meta.twitter?.creator && (
+
+ )}
+ >
+ );
+}
diff --git a/src/presets/components/head.tsx b/src/presets/components/head.tsx
new file mode 100644
index 0000000..cf07d05
--- /dev/null
+++ b/src/presets/components/head.tsx
@@ -0,0 +1,13 @@
+import type {
+ DetailedHTMLProps,
+ HTMLAttributes,
+ PropsWithChildren,
+} from "react";
+
+type Props = PropsWithChildren<
+ DetailedHTMLProps, HTMLHeadElement>
+>;
+
+export default function Head({ children, ...props }: Props) {
+ return {children};
+}
diff --git a/src/types/index.ts b/src/types/index.ts
index 4ede408..ed8ec18 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,5 +1,12 @@
import type { MatchedRoute, Server, WebSocketHandler } from "bun";
-import type { FC, JSX, PropsWithChildren, ReactNode } from "react";
+import type {
+ DetailedHTMLProps,
+ FC,
+ HtmlHTMLAttributes,
+ JSX,
+ PropsWithChildren,
+ ReactNode,
+} from "react";
export type ServerProps = {
params: Record;
@@ -145,11 +152,10 @@ export type PageDistGenParams = {
export type LivePageDistGenParams = {
component: ReactNode;
- head?: FC;
pageProps?: any;
module?: BunextPageModule;
+ root_module?: BunextRootModule;
bundledMap?: BundlerCTXMap;
- meta?: BunextPageModuleMeta;
routeParams?: BunxRouteParams;
debug?: boolean;
};
@@ -165,8 +171,14 @@ export type BunextPageModule = {
meta?: BunextPageModuleMeta | BunextPageModuleMetaFn;
Head?: FC;
config?: BunextRouteConfig;
+ html_props?: BunextHTMLProps;
};
+export type BunextHTMLProps = DetailedHTMLProps<
+ HtmlHTMLAttributes,
+ HTMLHtmlElement
+>;
+
export type BunextPageModuleMetaFn = (params: {
ctx: BunxRouteParams;
serverRes?: BunextPageModuleServerReturn;
@@ -253,11 +265,12 @@ export type GrabPageComponentRes = {
routeParams?: BunxRouteParams;
bundledMap?: BundlerCTXMap;
module: BunextPageModule;
- meta?: BunextPageModuleMeta;
- head?: FC;
+ root_module?: BunextRootModule;
debug?: boolean;
};
+export type BunextRootModule = BunextPageModule;
+
export type GrabPageReactBundledComponentRes = {
component: JSX.Element;
server_res?: BunextPageModuleServerReturn;
diff --git a/src/utils/rewrite-pages-module.ts b/src/utils/rewrite-pages-module.ts
index 5b5e75e..c6ee863 100644
--- a/src/utils/rewrite-pages-module.ts
+++ b/src/utils/rewrite-pages-module.ts
@@ -1,6 +1,8 @@
import grabAllPages from "./grab-all-pages";
import pagePathTransform from "./page-path-transform";
import stripServerSideLogic from "../functions/bundler/strip-server-side-logic";
+import grabRootFilePath from "../functions/server/web-pages/grab-root-file-path";
+import { existsSync } from "fs";
type Params = {
page_file_path?: string | string[];
@@ -21,20 +23,26 @@ export default async function rewritePagesModule(params?: Params) {
for (let i = 0; i < target_pages.length; i++) {
const page_path = target_pages[i];
- const dst_path = pagePathTransform({ page_path });
+ await transformFile(page_path);
+ }
- if (page_path.match(/__root\.tsx?/)) {
- continue;
- }
+ const { root_file_path } = grabRootFilePath();
- const origin_page_content = await Bun.file(page_path).text();
- const dst_page_content = stripServerSideLogic({
- txt_code: origin_page_content,
- file_path: page_path,
- });
-
- await Bun.write(dst_path, dst_page_content, {
- createPath: true,
- });
+ if (root_file_path && existsSync(root_file_path)) {
+ await transformFile(root_file_path);
}
}
+
+async function transformFile(page_path: string) {
+ const dst_path = pagePathTransform({ page_path });
+
+ const origin_page_content = await Bun.file(page_path).text();
+ const dst_page_content = stripServerSideLogic({
+ txt_code: origin_page_content,
+ file_path: page_path,
+ });
+
+ await Bun.write(dst_path, dst_page_content, {
+ createPath: true,
+ });
+}