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 = {