From 60ee353bf0ecda6b699e95ba7802eb5fed787752 Mon Sep 17 00:00:00 2001 From: Benjamin Toby Date: Tue, 24 Mar 2026 07:18:57 +0100 Subject: [PATCH] Refactor Server Paradigm. --- dist/commands/build/index.js | 8 +- dist/commands/dev/index.js | 4 +- dist/commands/start/index.js | 3 +- .../bundler/all-pages-bun-bundler.js | 15 ++- dist/functions/bundler/all-pages-bundler.js | 31 +++++- .../bundler/grab-client-hydration-script.js | 21 ++-- .../plugins/bun-skip-browser-plugin.js | 92 ++++++++++++---- dist/functions/bundler/record-artifacts.d.ts | 3 +- dist/functions/bundler/record-artifacts.js | 10 +- dist/functions/bunext-init.d.ts | 1 + dist/functions/bunext-init.js | 13 +-- dist/functions/server/watcher.js | 13 ++- .../server/web-pages/generate-web-html.d.ts | 2 +- .../server/web-pages/generate-web-html.js | 104 ++++++++++-------- ...b-page-response-from-component-return.d.ts | 2 +- ...web-page-response-from-component-return.js | 11 +- .../server/web-pages/grab-page-component.js | 98 +++++++---------- .../grab-page-react-component-string.js | 16 ++- .../web-pages/grab-page-server-path.d.ts | 7 ++ .../server/web-pages/grab-page-server-path.js | 11 ++ .../web-pages/grab-page-server-res.d.ts | 9 ++ .../server/web-pages/grab-page-server-res.js | 44 ++++++++ .../web-pages/grab-tsx-string-module.js | 51 ++++++--- .../server/web-pages/grab-web-meta-html.d.ts | 2 +- .../server/web-pages/grab-web-meta-html.js | 64 +---------- dist/index.d.ts | 2 +- dist/presets/components/head.d.ts | 4 + dist/presets/components/head.js | 4 + dist/types/index.d.ts | 16 ++- dist/utils/grab-all-pages.js | 6 +- dist/utils/log.d.ts | 2 +- dist/utils/log.js | 3 +- dist/utils/rewrite-pages-module.js | 30 +++-- package.json | 2 +- 34 files changed, 425 insertions(+), 279 deletions(-) create mode 100644 dist/functions/server/web-pages/grab-page-server-path.d.ts create mode 100644 dist/functions/server/web-pages/grab-page-server-path.js create mode 100644 dist/functions/server/web-pages/grab-page-server-res.d.ts create mode 100644 dist/functions/server/web-pages/grab-page-server-res.js create mode 100644 dist/presets/components/head.d.ts create mode 100644 dist/presets/components/head.js diff --git a/dist/commands/build/index.js b/dist/commands/build/index.js index 1121cfa..0bb08e3 100644 --- a/dist/commands/build/index.js +++ b/dist/commands/build/index.js @@ -1,23 +1,23 @@ import { Command } from "commander"; import { log } from "../../utils/log"; import init from "../../functions/init"; -import rewritePagesModule from "../../utils/rewrite-pages-module"; +// import rewritePagesModule from "../../utils/rewrite-pages-module"; import allPagesBunBundler from "../../functions/bundler/all-pages-bun-bundler"; import grabDirNames from "../../utils/grab-dir-names"; import { rmSync } from "fs"; +import allPagesBundler from "../../functions/bundler/all-pages-bundler"; const { HYDRATION_DST_DIR, BUNX_CWD_PAGES_REWRITE_DIR } = grabDirNames(); export default function () { return new Command("build") .description("Build Project") .action(async () => { - process.env.NODE_ENV = "production"; - process.env.BUILD = "true"; try { rmSync(HYDRATION_DST_DIR, { recursive: true }); rmSync(BUNX_CWD_PAGES_REWRITE_DIR, { recursive: true }); } catch (error) { } - await rewritePagesModule(); + global.SKIPPED_BROWSER_MODULES = new Set(); + // await rewritePagesModule(); await init(); log.banner(); log.build("Building Project ..."); diff --git a/dist/commands/dev/index.js b/dist/commands/dev/index.js index 884090a..fe5645e 100644 --- a/dist/commands/dev/index.js +++ b/dist/commands/dev/index.js @@ -2,9 +2,9 @@ import { Command } from "commander"; import startServer from "../../functions/server/start-server"; import { log } from "../../utils/log"; import bunextInit from "../../functions/bunext-init"; -import rewritePagesModule from "../../utils/rewrite-pages-module"; import grabDirNames from "../../utils/grab-dir-names"; import { rmSync } from "fs"; +import allPagesBunBundler from "../../functions/bundler/all-pages-bun-bundler"; const { HYDRATION_DST_DIR, BUNX_CWD_PAGES_REWRITE_DIR } = grabDirNames(); export default function () { return new Command("dev") @@ -17,8 +17,8 @@ export default function () { rmSync(BUNX_CWD_PAGES_REWRITE_DIR, { recursive: true }); } catch (error) { } - await rewritePagesModule(); await bunextInit(); + await allPagesBunBundler(); await startServer(); }); } diff --git a/dist/commands/start/index.js b/dist/commands/start/index.js index be8edc0..e87c3e0 100644 --- a/dist/commands/start/index.js +++ b/dist/commands/start/index.js @@ -2,13 +2,14 @@ import { Command } from "commander"; import startServer from "../../functions/server/start-server"; import { log } from "../../utils/log"; import bunextInit from "../../functions/bunext-init"; +import allPagesBunBundler from "../../functions/bundler/all-pages-bun-bundler"; export default function () { return new Command("start") .description("Start production server") .action(async () => { - process.env.NODE_ENV = "production"; log.info("Starting production server ..."); await bunextInit(); + await allPagesBunBundler(); await startServer(); }); } diff --git a/dist/functions/bundler/all-pages-bun-bundler.js b/dist/functions/bundler/all-pages-bun-bundler.js index 5f7fcf9..4622a3c 100644 --- a/dist/functions/bundler/all-pages-bun-bundler.js +++ b/dist/functions/bundler/all-pages-bun-bundler.js @@ -7,6 +7,7 @@ import path from "path"; import grabClientHydrationScript from "./grab-client-hydration-script"; import { mkdirSync, rmSync } from "fs"; import recordArtifacts from "./record-artifacts"; +import BunSkipNonBrowserPlugin from "./plugins/bun-skip-browser-plugin"; const { HYDRATION_DST_DIR, BUNX_HYDRATION_SRC_DIR, BUNX_TMP_DIR } = grabDirNames(); export default async function allPagesBunBundler(params) { const { target = "browser", page_file_paths } = params || {}; @@ -37,15 +38,16 @@ export default async function allPagesBunBundler(params) { if (entryToPage.size === 0) return; const buildStart = performance.now(); + const define = { + "process.env.NODE_ENV": JSON.stringify(dev ? "development" : "production"), + }; const result = await Bun.build({ entrypoints: [...entryToPage.keys()], outdir: HYDRATION_DST_DIR, root: BUNX_HYDRATION_SRC_DIR, - minify: true, + minify: !dev, format: "esm", - define: { - "process.env.NODE_ENV": JSON.stringify(dev ? "development" : "production"), - }, + define, naming: { entry: "[dir]/[hash].[ext]", chunk: "chunks/[hash].[ext]", @@ -94,7 +96,10 @@ export default async function allPagesBunBundler(params) { }); } if (artifacts?.[0]) { - await recordArtifacts({ artifacts }); + await recordArtifacts({ + artifacts, + page_file_paths, + }); } const elapsed = (performance.now() - buildStart).toFixed(0); log.success(`[Built] in ${elapsed}ms`); diff --git a/dist/functions/bundler/all-pages-bundler.js b/dist/functions/bundler/all-pages-bundler.js index 045fab9..3d5a197 100644 --- a/dist/functions/bundler/all-pages-bundler.js +++ b/dist/functions/bundler/all-pages-bundler.js @@ -8,6 +8,7 @@ import grabClientHydrationScript from "./grab-client-hydration-script"; import grabArtifactsFromBundledResults from "./grab-artifacts-from-bundled-result"; import { writeFileSync } from "fs"; import recordArtifacts from "./record-artifacts"; +import stripServerSideLogic from "./strip-server-side-logic"; const { HYDRATION_DST_DIR, HYDRATION_DST_DIR_MAP_JSON_FILE } = grabDirNames(); let build_starts = 0; const MAX_BUILD_STARTS = 10; @@ -23,7 +24,7 @@ export default async function allPagesBundler(params) { const virtualEntries = {}; const dev = isDevelopment(); for (const page of target_pages) { - const key = page.transformed_path; + const key = page.local_path; const txt = await grabClientHydrationScript({ page_local_path: page.local_path, }); @@ -32,6 +33,11 @@ export default async function allPagesBundler(params) { // } if (!txt) continue; + // const final_tsx = stripServerSideLogic({ + // txt_code: txt, + // file_path: key, + // }); + // console.log("final_tsx", final_tsx); virtualEntries[key] = txt; } const virtualPlugin = { @@ -66,6 +72,28 @@ export default async function allPagesBundler(params) { }, }; const entryPoints = Object.keys(virtualEntries).map((k) => `virtual:${k}`); + // let alias: any = {}; + // const excludes = [ + // "bun:sqlite", + // "path", + // "url", + // "events", + // "util", + // "crypto", + // "net", + // "tls", + // "fs", + // "node:path", + // "node:url", + // "node:process", + // "node:fs", + // "node:timers/promises", + // ]; + // for (let i = 0; i < excludes.length; i++) { + // const exclude = excludes[i]; + // alias[exclude] = "./empty.js"; + // } + // console.log("alias", alias); const result = await esbuild.build({ entryPoints, outdir: HYDRATION_DST_DIR, @@ -89,6 +117,7 @@ export default async function allPagesBundler(params) { "react-dom/client", "react/jsx-runtime", ], + // alias, }); if (result.errors.length > 0) { for (const error of result.errors) { diff --git a/dist/functions/bundler/grab-client-hydration-script.js b/dist/functions/bundler/grab-client-hydration-script.js index 9c91487..a7cc607 100644 --- a/dist/functions/bundler/grab-client-hydration-script.js +++ b/dist/functions/bundler/grab-client-hydration-script.js @@ -4,24 +4,27 @@ 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(); export default async function grabClientHydrationScript({ page_local_path, }) { const { ClientRootElementIDName, ClientRootComponentWindowName, ClientWindowPagePropsName, } = grabConstants(); - 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 { root_file_path } = grabRootFilePath(); + // const target_path = pagePathTransform({ page_path: page_local_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 (root_file_path) { + txt += `import Root from "${root_file_path}";\n`; } - txt += `import Page from "${target_path}";\n\n`; + txt += `import Page from "${page_local_path}";\n\n`; txt += `const pageProps = window.${ClientWindowPagePropsName} || {};\n`; - if (does_root_exist) { - txt += `const component = \n`; + if (root_file_path) { + txt += `const component = \n`; } else { - txt += `const component = \n`; + txt += `const component = \n`; } txt += `if (window.${ClientRootComponentWindowName}?.render) {\n`; txt += ` window.${ClientRootComponentWindowName}.render(component);\n`; diff --git a/dist/functions/bundler/plugins/bun-skip-browser-plugin.js b/dist/functions/bundler/plugins/bun-skip-browser-plugin.js index e8be583..dfc2770 100644 --- a/dist/functions/bundler/plugins/bun-skip-browser-plugin.js +++ b/dist/functions/bundler/plugins/bun-skip-browser-plugin.js @@ -1,31 +1,75 @@ +import { log } from "../../../utils/log"; const BunSkipNonBrowserPlugin = { name: "skip-non-browser", setup(build) { - build.onResolve({ filter: /^(bun:|node:)/ }, (args) => { - return { path: args.path, external: true }; + const skipFilter = /^(bun:|node:|fs$|path$|os$|crypto$|net$|events$|util$|tls$|url$|process$)/; + // const skipped_modules = new Set(); + build.onResolve({ filter: skipFilter }, (args) => { + global.SKIPPED_BROWSER_MODULES.add(args.path); + return { + path: args.path, + namespace: "skipped", + // external: true, + }; }); - build.onResolve({ filter: /^[^./]/ }, (args) => { - // If it's a built-in like 'fs' or 'path', skip it immediately - const excludes = [ - "fs", - "path", - "os", - "crypto", - "net", - "events", - "util", - ]; - if (excludes.includes(args.path) || args.path.startsWith("node:")) { - return { path: args.path, external: true }; - } - try { - Bun.resolveSync(args.path, args.importer || process.cwd()); - return null; - } - catch (e) { - console.warn(`[Skip] Mark as external: ${args.path}`); - return { path: args.path, external: true }; - } + // build.onEnd(() => { + // log.warn(`global.SKIPPED_BROWSER_MODULES`, [ + // ...global.SKIPPED_BROWSER_MODULES, + // ]); + // }); + // build.onResolve({ filter: /^[^./]/ }, (args) => { + // // If it's a built-in like 'fs' or 'path', skip it immediately + // const excludes = [ + // "fs", + // "path", + // "os", + // "crypto", + // "net", + // "events", + // "util", + // "tls", + // ]; + // if (excludes.includes(args.path) || args.path.startsWith("node:")) { + // return { + // path: args.path, + // // namespace: "skipped", + // external: true, + // }; + // } + // try { + // Bun.resolveSync(args.path, args.importer || process.cwd()); + // return null; + // } catch (e) { + // console.warn(`[Skip] Mark as external: ${args.path}`); + // return { + // path: args.path, + // // namespace: "skipped", + // external: true, + // }; + // } + // }); + build.onLoad({ filter: /.*/, namespace: "skipped" }, (args) => { + return { + contents: ` + const proxy = new Proxy(() => proxy, { + get: () => proxy, + construct: () => proxy, + }); + + export const Database = proxy; + export const join = proxy; + export const fileURLToPath = proxy; + export const arch = proxy; + export const platform = proxy; + export const statSync = proxy; + + export const $H = proxy; + export const _ = proxy; + + export default proxy; + `, + loader: "js", + }; }); }, }; diff --git a/dist/functions/bundler/record-artifacts.d.ts b/dist/functions/bundler/record-artifacts.d.ts index 4ce4440..05cfdd0 100644 --- a/dist/functions/bundler/record-artifacts.d.ts +++ b/dist/functions/bundler/record-artifacts.d.ts @@ -1,6 +1,7 @@ import type { BundlerCTXMap } from "../../types"; type Params = { artifacts: BundlerCTXMap[]; + page_file_paths?: string[]; }; -export default function recordArtifacts({ artifacts }: Params): Promise; +export default function recordArtifacts({ artifacts, page_file_paths, }: Params): Promise; export {}; diff --git a/dist/functions/bundler/record-artifacts.js b/dist/functions/bundler/record-artifacts.js index bc8adfb..ff1c4c6 100644 --- a/dist/functions/bundler/record-artifacts.js +++ b/dist/functions/bundler/record-artifacts.js @@ -1,6 +1,7 @@ import grabDirNames from "../../utils/grab-dir-names"; +import _ from "lodash"; const { HYDRATION_DST_DIR_MAP_JSON_FILE } = grabDirNames(); -export default async function recordArtifacts({ artifacts }) { +export default async function recordArtifacts({ artifacts, page_file_paths, }) { const artifacts_map = {}; for (const artifact of artifacts) { if (artifact?.local_path) { @@ -8,7 +9,10 @@ export default async function recordArtifacts({ artifacts }) { } } 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(HYDRATION_DST_DIR_MAP_JSON_FILE, JSON.stringify(artifacts_map, null, 4)); + // await Bun.write( + // HYDRATION_DST_DIR_MAP_JSON_FILE, + // JSON.stringify(artifacts_map, null, 4), + // ); } diff --git a/dist/functions/bunext-init.d.ts b/dist/functions/bunext-init.d.ts index c4e1a8d..8c78335 100644 --- a/dist/functions/bunext-init.d.ts +++ b/dist/functions/bunext-init.d.ts @@ -22,5 +22,6 @@ declare global { var CURRENT_VERSION: string | undefined; var PAGE_FILES: PageFiles[]; var ROOT_FILE_UPDATED: boolean; + var SKIPPED_BROWSER_MODULES: Set; } export default function bunextInit(): Promise; diff --git a/dist/functions/bunext-init.js b/dist/functions/bunext-init.js index 4d2c6ab..54501fe 100644 --- a/dist/functions/bunext-init.js +++ b/dist/functions/bunext-init.js @@ -1,13 +1,11 @@ import ora, {} from "ora"; import grabDirNames from "../utils/grab-dir-names"; -import { readFileSync } from "fs"; +import {} from "fs"; import init from "./init"; import isDevelopment from "../utils/is-development"; -import allPagesBundler from "./bundler/all-pages-bundler"; import watcher from "./server/watcher"; import { log } from "../utils/log"; import cron from "./server/cron"; -import EJSON from "../utils/ejson"; import allPagesBunBundler from "./bundler/all-pages-bun-bundler"; const { PAGES_DIR, HYDRATION_DST_DIR_MAP_JSON_FILE } = grabDirNames(); export default async function bunextInit() { @@ -17,6 +15,7 @@ export default async function bunextInit() { global.BUNDLER_CTX_MAP = {}; global.BUNDLER_REBUILDS = 0; global.PAGE_FILES = []; + global.SKIPPED_BROWSER_MODULES = new Set(); await init(); log.banner(); const router = new Bun.FileSystemRouter({ @@ -26,17 +25,9 @@ export default async function bunextInit() { global.ROUTER = router; const is_dev = isDevelopment(); if (is_dev) { - // await allPagesBundler(); - await allPagesBunBundler(); watcher(); } else { - const artifacts = EJSON.parse(readFileSync(HYDRATION_DST_DIR_MAP_JSON_FILE, "utf-8")); - if (!artifacts) { - log.error("Please build first."); - process.exit(1); - } - global.BUNDLER_CTX_MAP = artifacts; cron(); } } diff --git a/dist/functions/server/watcher.js b/dist/functions/server/watcher.js index af0890c..4dc191e 100644 --- a/dist/functions/server/watcher.js +++ b/dist/functions/server/watcher.js @@ -3,7 +3,7 @@ import path from "path"; import grabDirNames from "../../utils/grab-dir-names"; import rebuildBundler from "./rebuild-bundler"; import { log } from "../../utils/log"; -import rewritePagesModule from "../../utils/rewrite-pages-module"; +// import rewritePagesModule from "../../utils/rewrite-pages-module"; const { ROOT_DIR } = grabDirNames(); export default async function watcher() { const pages_src_watcher = watch(ROOT_DIR, { @@ -62,14 +62,15 @@ async function fullRebuild(params) { try { const { msg } = params || {}; global.RECOMPILING = true; - const target_file_paths = global.HMR_CONTROLLERS.map((hmr) => hmr.target_map?.local_path).filter((f) => typeof f == "string"); - await rewritePagesModule({ - page_file_path: target_file_paths, - }); + // const target_file_paths = global.HMR_CONTROLLERS.map( + // (hmr) => hmr.target_map?.local_path, + // ).filter((f) => typeof f == "string"); + // await rewritePagesModule(); if (msg) { log.watch(msg); } - await rebuildBundler({ target_file_paths }); + await rebuildBundler(); + // await rebuildBundler({ target_file_paths }); } catch (error) { log.error(error); diff --git a/dist/functions/server/web-pages/generate-web-html.d.ts b/dist/functions/server/web-pages/generate-web-html.d.ts index 2825167..193b716 100644 --- a/dist/functions/server/web-pages/generate-web-html.d.ts +++ b/dist/functions/server/web-pages/generate-web-html.d.ts @@ -1,2 +1,2 @@ import type { LivePageDistGenParams } from "../../../types"; -export default function genWebHTML({ component, pageProps, bundledMap, head: Head, module, meta, routeParams, debug, }: LivePageDistGenParams): Promise; +export default function genWebHTML({ component, pageProps, bundledMap, module, routeParams, debug, root_module, }: LivePageDistGenParams): Promise; diff --git a/dist/functions/server/web-pages/generate-web-html.js b/dist/functions/server/web-pages/generate-web-html.js index 08d13d4..1fef9b0 100644 --- a/dist/functions/server/web-pages/generate-web-html.js +++ b/dist/functions/server/web-pages/generate-web-html.js @@ -1,4 +1,4 @@ -import { jsx as _jsx } from "react/jsx-runtime"; +import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { renderToString } from "react-dom/server"; import grabContants from "../../../utils/grab-constants"; import EJSON from "../../../utils/ejson"; @@ -14,56 +14,68 @@ try { _reactVersion = JSON.parse(readFileSync(path.join(process.cwd(), "node_modules/react/package.json"), "utf-8")).version; } catch { } -export default async function genWebHTML({ component, pageProps, bundledMap, head: Head, module, meta, routeParams, debug, }) { +export default async function genWebHTML({ component, pageProps, bundledMap, module, routeParams, debug, root_module, }) { 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(_jsx(Head, { serverRes: pageProps, ctx: routeParams })) - : ""; - 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; + const html_props = { + ...module?.html_props, + ...root_module?.html_props, + }; + const Head = module?.Head; + const RootHead = root_module?.Head; + const dev = isDevelopment(); + const devSuffix = dev ? "?dev" : ""; + const browser_imports = { + react: `https://esm.sh/react@${_reactVersion}`, + "react-dom": `https://esm.sh/react-dom@${_reactVersion}`, + "react-dom/client": `https://esm.sh/react-dom@${_reactVersion}/client`, + "react/jsx-runtime": `https://esm.sh/react@${_reactVersion}/jsx-runtime`, + }; + if (dev) { + browser_imports["react/jsx-dev-runtime"] = + `https://esm.sh/react@${_reactVersion}/jsx-dev-runtime`; } - if (isDevelopment()) { - html += `\n`; - } - if (headHTML) { - html += ` ${headHTML}\n`; - } - html += ` \n`; - html += ` \n`; - html += `
${componentHTML}
\n`; - html += ` \n`; - html += `\n`; + const importMap = JSON.stringify({ + imports: browser_imports, + }); + let final_component = (_jsxs("html", { ...html_props, children: [_jsxs("head", { children: [_jsx("meta", { charSet: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), root_meta ? grabWebMetaHTML({ meta: root_meta }) : null, page_meta ? grabWebMetaHTML({ meta: page_meta }) : null, bundledMap?.css_path ? (_jsx("link", { rel: "stylesheet", href: `/${bundledMap.css_path}` })) : null, _jsx("script", { dangerouslySetInnerHTML: { + __html: `window.${ClientWindowPagePropsName} = ${serializedProps}`, + } }), bundledMap?.path ? (_jsxs(_Fragment, { children: [_jsx("script", { type: "importmap", dangerouslySetInnerHTML: { + __html: importMap, + }, fetchPriority: "high" }), _jsx("script", { src: `/${bundledMap.path}`, type: "module", id: AppData["BunextClientHydrationScriptID"], defer: true })] })) : null, is_dev ? (_jsx("script", { defer: true, dangerouslySetInnerHTML: { + __html: page_hydration_script, + } })) : null, RootHead ? (_jsx(RootHead, { serverRes: pageProps, ctx: routeParams })) : null, Head ? _jsx(Head, { serverRes: pageProps, ctx: routeParams }) : null] }), _jsx("body", { children: _jsx("div", { id: ClientRootElementIDName, suppressHydrationWarning: !dev, children: component }) })] })); + let html = `\n`; + // const stream = await renderToReadableStream(final_component, { + // onError(error: any) { + // // This is where you "omit" or handle the errors + // // You can log it silently or ignore it + // if (error.message.includes('unique "key" prop')) return; + // console.error(error); + // }, + // }); + // // 2. Convert the Web Stream to a String (Bun-optimized) + // const htmlBody = await new Response(stream).text(); + // html += htmlBody; + html += renderToString(final_component); return html; } diff --git a/dist/functions/server/web-pages/generate-web-page-response-from-component-return.d.ts b/dist/functions/server/web-pages/generate-web-page-response-from-component-return.d.ts index f174f3d..e23db85 100644 --- a/dist/functions/server/web-pages/generate-web-page-response-from-component-return.d.ts +++ b/dist/functions/server/web-pages/generate-web-page-response-from-component-return.d.ts @@ -1,2 +1,2 @@ import type { GrabPageComponentRes } from "../../../types"; -export default function generateWebPageResponseFromComponentReturn({ component, module, bundledMap, head, meta, routeParams, serverRes, debug, }: GrabPageComponentRes): Promise; +export default function generateWebPageResponseFromComponentReturn({ component, module, bundledMap, routeParams, serverRes, debug, root_module, }: GrabPageComponentRes): Promise; diff --git a/dist/functions/server/web-pages/generate-web-page-response-from-component-return.js b/dist/functions/server/web-pages/generate-web-page-response-from-component-return.js index a7ac2a3..ee45b5d 100644 --- a/dist/functions/server/web-pages/generate-web-page-response-from-component-return.js +++ b/dist/functions/server/web-pages/generate-web-page-response-from-component-return.js @@ -1,17 +1,17 @@ +import _ from "lodash"; import isDevelopment from "../../../utils/is-development"; import { log } from "../../../utils/log"; import writeCache from "../../cache/write-cache"; import genWebHTML from "./generate-web-html"; -export default async function generateWebPageResponseFromComponentReturn({ component, module, bundledMap, head, meta, routeParams, serverRes, debug, }) { +export default async function generateWebPageResponseFromComponentReturn({ component, module, bundledMap, routeParams, serverRes, debug, root_module, }) { const html = await genWebHTML({ component, pageProps: serverRes, bundledMap, module, - meta, - head, routeParams, debug, + root_module, }); if (debug) { log.info("html", html); @@ -36,8 +36,9 @@ export default async function generateWebPageResponseFromComponentReturn({ compo Expires: "0", }; } - const cache_page = module.config?.cachePage || serverRes?.cachePage || false; - const expiry_seconds = module.config?.cacheExpiry || serverRes?.cacheExpiry; + const config = _.merge(root_module?.config, module.config); + const cache_page = config?.cachePage || serverRes?.cachePage || false; + const expiry_seconds = config?.cacheExpiry || serverRes?.cacheExpiry; if (cache_page && routeParams?.url) { const key = routeParams.url.pathname + (routeParams.url.search || ""); writeCache({ diff --git a/dist/functions/server/web-pages/grab-page-component.js b/dist/functions/server/web-pages/grab-page-component.js index 57089fd..0e80471 100644 --- a/dist/functions/server/web-pages/grab-page-component.js +++ b/dist/functions/server/web-pages/grab-page-component.js @@ -4,6 +4,8 @@ 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"; +import grabPageServerPath from "./grab-page-server-path"; class NotFoundError extends Error { } export default async function grabPageComponent({ req, file_path: passed_file_path, debug, }) { @@ -35,6 +37,7 @@ export default async function grabPageComponent({ req, file_path: passed_file_pa } 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); @@ -43,72 +46,52 @@ export default async function grabPageComponent({ req, file_path: passed_file_pa log.info(`bundledMap:`, bundledMap); } const { root_file_path } = grabRootFilePath(); + const root_module = root_file_path + ? await import(`${root_file_path}?t=${now}`) + : undefined; + const { server_file_path: root_server_file_path } = root_file_path + ? grabPageServerPath({ file_path: root_file_path }) + : {}; + const root_server_module = root_server_file_path + ? await import(`${root_server_file_path}?t=${now}`) + : undefined; + const root_server_fn = root_server_module?.default || root_server_module?.server; + const rootServerRes = root_server_fn + ? await grabPageServerRes({ + server_function: root_server_fn, + url, + query: match?.query, + routeParams, + }) + : undefined; + if (debug) { + log.info(`rootServerRes:`, rootServerRes); + } const module = await import(`${file_path}?t=${now}`); + const { server_file_path } = grabPageServerPath({ file_path }); + const server_module = server_file_path + ? await import(`${server_file_path}?t=${now}`) + : undefined; if (debug) { log.info(`module:`, module); } - const serverRes = await (async () => { - const default_props = { - url: { - ..._.pick(url, [ - "host", - "hostname", - "pathname", - "origin", - "port", - "search", - "searchParams", - "hash", - "href", - "password", - "protocol", - "username", - ]), - }, + const server_fn = server_module?.default || server_module?.server; + const serverRes = server_fn + ? await grabPageServerRes({ + server_function: server_fn, + url, query: match?.query, - }; - 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, - }; - } - })(); + routeParams, + }) + : undefined; if (debug) { log.info(`serverRes:`, serverRes); } - const meta = module.meta - ? typeof module.meta == "function" && routeParams - ? await module.meta({ - ctx: routeParams, - serverRes, - }) - : typeof module.meta == "object" - ? module.meta - : undefined - : undefined; - if (debug) { - log.info(`meta:`, meta); - } - const Head = module.Head; + const mergedServerRes = _.merge(rootServerRes || {}, serverRes || {}); const { component } = (await grabPageBundledReactComponent({ file_path, root_file_path, - server_res: serverRes, + server_res: mergedServerRes, })) || {}; if (!component) { throw new Error(`Couldn't grab page component`); @@ -118,12 +101,11 @@ export default async function grabPageComponent({ req, file_path: passed_file_pa } return { component, - serverRes, + serverRes: mergedServerRes, routeParams, module, bundledMap, - meta, - head: Head, + root_module, }; } catch (error) { diff --git a/dist/functions/server/web-pages/grab-page-react-component-string.js b/dist/functions/server/web-pages/grab-page-react-component-string.js index ddae2cf..54d3471 100644 --- a/dist/functions/server/web-pages/grab-page-react-component-string.js +++ b/dist/functions/server/web-pages/grab-page-react-component-string.js @@ -2,21 +2,29 @@ import EJSON from "../../../utils/ejson"; import pagePathTransform from "../../../utils/page-path-transform"; export default function grabPageReactComponentString({ file_path, root_file_path, server_res, }) { try { - const target_path = pagePathTransform({ page_path: file_path }); + // 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 || {}) ?? "{}"); + // Import Root from its original source path so that all sub-components + // that import __root (e.g. AppContext) resolve to the same module instance. + // Using the rewritten .bunext/pages/__root would create a separate + // createContext() call, breaking context for any sub-component that + // imports AppContext via a relative path to the source __root. if (root_file_path) { tsx += `import Root from "${root_file_path}"\n`; } - tsx += `import Page from "${target_path}"\n`; + tsx += `import Page from "${file_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) { - tsx += ` \n`; + tsx += ` \n`; } else { - tsx += ` \n`; + tsx += ` \n`; } tsx += ` )\n`; tsx += `}\n`; diff --git a/dist/functions/server/web-pages/grab-page-server-path.d.ts b/dist/functions/server/web-pages/grab-page-server-path.d.ts new file mode 100644 index 0000000..a4e1478 --- /dev/null +++ b/dist/functions/server/web-pages/grab-page-server-path.d.ts @@ -0,0 +1,7 @@ +type Params = { + file_path: string; +}; +export default function grabPageServerPath({ file_path }: Params): { + server_file_path: string | undefined; +}; +export {}; diff --git a/dist/functions/server/web-pages/grab-page-server-path.js b/dist/functions/server/web-pages/grab-page-server-path.js new file mode 100644 index 0000000..285c55a --- /dev/null +++ b/dist/functions/server/web-pages/grab-page-server-path.js @@ -0,0 +1,11 @@ +import { existsSync } from "fs"; +export default function grabPageServerPath({ file_path }) { + const page_server_ts_file = file_path.replace(/\.tsx?$/, ".server.ts"); + const page_server_tsx_file = file_path.replace(/\.tsx?$/, ".server.tsx"); + const server_file_path = existsSync(page_server_ts_file) + ? page_server_ts_file + : existsSync(page_server_tsx_file) + ? page_server_tsx_file + : undefined; + return { server_file_path }; +} diff --git a/dist/functions/server/web-pages/grab-page-server-res.d.ts b/dist/functions/server/web-pages/grab-page-server-res.d.ts new file mode 100644 index 0000000..10025db --- /dev/null +++ b/dist/functions/server/web-pages/grab-page-server-res.d.ts @@ -0,0 +1,9 @@ +import type { BunextPageModuleServerReturn, BunextPageServerFn, BunxRouteParams } from "../../../types"; +type Params = { + url?: URL; + server_function: BunextPageServerFn; + query?: Record; + routeParams?: BunxRouteParams; +}; +export default function grabPageServerRes({ url, query, routeParams, server_function, }: Params): Promise; +export {}; diff --git a/dist/functions/server/web-pages/grab-page-server-res.js b/dist/functions/server/web-pages/grab-page-server-res.js new file mode 100644 index 0000000..83c2fc7 --- /dev/null +++ b/dist/functions/server/web-pages/grab-page-server-res.js @@ -0,0 +1,44 @@ +import _ from "lodash"; +export default async function grabPageServerRes({ url, query, routeParams, server_function, }) { + const default_props = { + url: url + ? { + ..._.pick(url, [ + "host", + "hostname", + "pathname", + "origin", + "port", + "search", + "searchParams", + "hash", + "href", + "password", + "protocol", + "username", + ]), + } + : null, + query, + }; + try { + if (routeParams) { + const serverData = await server_function({ + ...routeParams, + query: { ...routeParams.query, ...query }, + }); + return { + ...serverData, + ...default_props, + }; + } + return { + ...default_props, + }; + } + catch (error) { + return { + ...default_props, + }; + } +} diff --git a/dist/functions/server/web-pages/grab-tsx-string-module.js b/dist/functions/server/web-pages/grab-tsx-string-module.js index b1f4c27..c5ec7ff 100644 --- a/dist/functions/server/web-pages/grab-tsx-string-module.js +++ b/dist/functions/server/web-pages/grab-tsx-string-module.js @@ -1,37 +1,58 @@ 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"; +import BunSkipNonBrowserPlugin from "../../bundler/plugins/bun-skip-browser-plugin"; export default async function grabTsxStringModule({ tsx, file_path, }) { const dev = isDevelopment(); const { BUNX_CWD_MODULE_CACHE_DIR } = grabDirNames(); const trimmed_file_path = file_path .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); + const build = await Bun.build({ + entrypoints: [src_file_path], format: "esm", - target: "es2020", - platform: "node", + target: "bun", 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, + plugins: [tailwindcss, BunSkipNonBrowserPlugin], + jsx: { + runtime: "automatic", + development: dev, + }, + outdir: BUNX_CWD_MODULE_CACHE_DIR, }); Loader.registry.delete(out_file_path); const module = await import(`${out_file_path}?t=${Date.now()}`); return module; } +// 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/dist/functions/server/web-pages/grab-web-meta-html.d.ts b/dist/functions/server/web-pages/grab-web-meta-html.d.ts index 9d90be8..e82ddea 100644 --- a/dist/functions/server/web-pages/grab-web-meta-html.d.ts +++ b/dist/functions/server/web-pages/grab-web-meta-html.d.ts @@ -2,5 +2,5 @@ import type { BunextPageModuleMeta } from "../../../types"; type Params = { meta: BunextPageModuleMeta; }; -export default function grabWebMetaHTML({ meta }: Params): string; +export default function grabWebMetaHTML({ meta }: Params): import("react/jsx-runtime").JSX.Element; export {}; diff --git a/dist/functions/server/web-pages/grab-web-meta-html.js b/dist/functions/server/web-pages/grab-web-meta-html.js index e49986c..ef41d56 100644 --- a/dist/functions/server/web-pages/grab-web-meta-html.js +++ b/dist/functions/server/web-pages/grab-web-meta-html.js @@ -1,61 +1,9 @@ -import { escape } from "lodash"; +import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; export default function grabWebMetaHTML({ meta }) { - let html = ``; - if (meta.title) { - html += ` ${escape(meta.title)}\n`; - } - if (meta.description) { - html += ` \n`; - } - if (meta.keywords) { - const keywords = Array.isArray(meta.keywords) + const keywords = meta.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; + : meta.keywords + : undefined; + return (_jsxs(_Fragment, { children: [meta.title && _jsx("title", { children: meta.title }), meta.description && (_jsx("meta", { name: "description", content: meta.description })), keywords && _jsx("meta", { name: "keywords", content: keywords }), meta.author && _jsx("meta", { name: "author", content: meta.author }), meta.robots && _jsx("meta", { name: "robots", content: meta.robots }), meta.canonical && (_jsx("link", { rel: "canonical", href: meta.canonical })), meta.themeColor && (_jsx("meta", { name: "theme-color", content: meta.themeColor })), meta.og?.title && (_jsx("meta", { property: "og:title", content: meta.og.title })), meta.og?.description && (_jsx("meta", { property: "og:description", content: meta.og.description })), meta.og?.image && (_jsx("meta", { property: "og:image", content: meta.og.image })), meta.og?.url && (_jsx("meta", { property: "og:url", content: meta.og.url })), meta.og?.type && (_jsx("meta", { property: "og:type", content: meta.og.type })), meta.og?.siteName && (_jsx("meta", { property: "og:site_name", content: meta.og.siteName })), meta.og?.locale && (_jsx("meta", { property: "og:locale", content: meta.og.locale })), meta.twitter?.card && (_jsx("meta", { name: "twitter:card", content: meta.twitter.card })), meta.twitter?.title && (_jsx("meta", { name: "twitter:title", content: meta.twitter.title })), meta.twitter?.description && (_jsx("meta", { name: "twitter:description", content: meta.twitter.description })), meta.twitter?.image && (_jsx("meta", { name: "twitter:image", content: meta.twitter.image })), meta.twitter?.site && (_jsx("meta", { name: "twitter:site", content: meta.twitter.site })), meta.twitter?.creator && (_jsx("meta", { name: "twitter:creator", content: meta.twitter.creator }))] })); } diff --git a/dist/index.d.ts b/dist/index.d.ts index 7dc0b3b..94c9da9 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -6,7 +6,7 @@ declare const bunext: { info: (msg: string, log?: any) => void; success: (msg: string, log?: any) => void; error: (msg: string | Error, log?: any) => void; - warn: (msg: string) => void; + warn: (msg: string, log?: any) => void; build: (msg: string) => void; watch: (msg: string) => void; server: (url: string) => void; diff --git a/dist/presets/components/head.d.ts b/dist/presets/components/head.d.ts new file mode 100644 index 0000000..f2f837e --- /dev/null +++ b/dist/presets/components/head.d.ts @@ -0,0 +1,4 @@ +import type { DetailedHTMLProps, HTMLAttributes, PropsWithChildren } from "react"; +type Props = PropsWithChildren, HTMLHeadElement>>; +export default function Head({ children, ...props }: Props): import("react/jsx-runtime").JSX.Element; +export {}; diff --git a/dist/presets/components/head.js b/dist/presets/components/head.js new file mode 100644 index 0000000..7a4b680 --- /dev/null +++ b/dist/presets/components/head.js @@ -0,0 +1,4 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +export default function Head({ children, ...props }) { + return _jsx("head", { ...props, children: children }); +} diff --git a/dist/types/index.d.ts b/dist/types/index.d.ts index 8a9b4ca..829b500 100644 --- a/dist/types/index.d.ts +++ b/dist/types/index.d.ts @@ -1,5 +1,5 @@ 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; searchParams: Record; @@ -129,11 +129,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; }; @@ -143,11 +142,16 @@ export type BunextPageHeadFCProps = { }; export type BunextPageModule = { default: FC; - server?: BunextPageServerFn; meta?: BunextPageModuleMeta | BunextPageModuleMetaFn; Head?: FC; config?: BunextRouteConfig; + html_props?: BunextHTMLProps; }; +export type BunextPageServerModule = { + default?: BunextPageServerFn; + server?: BunextPageServerFn; +}; +export type BunextHTMLProps = DetailedHTMLProps, HTMLHtmlElement>; export type BunextPageModuleMetaFn = (params: { ctx: BunxRouteParams; serverRes?: BunextPageModuleServerReturn; @@ -235,10 +239,10 @@ 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/dist/utils/grab-all-pages.js b/dist/utils/grab-all-pages.js index cbbd83b..0d546af 100644 --- a/dist/utils/grab-all-pages.js +++ b/dist/utils/grab-all-pages.js @@ -20,8 +20,9 @@ function grabPageDirRecursively({ page_dir }) { } for (let i = 0; i < pages.length; i++) { const page = pages[i]; + const page_name = page.split("/").pop(); const full_page_path = path.join(page_dir, page); - if (!existsSync(full_page_path)) { + if (!existsSync(full_page_path) || !page_name) { continue; } if (page.match(new RegExp(`${AppNames["RootPagesComponentName"]}`))) { @@ -30,6 +31,9 @@ function grabPageDirRecursively({ page_dir }) { if (page.match(/\(|\)|--|\/api\//)) { continue; } + if (page_name.split(".").length > 2) { + continue; + } const page_stat = statSync(full_page_path); if (page_stat.isDirectory()) { if (page.match(/\(|\)/)) diff --git a/dist/utils/log.d.ts b/dist/utils/log.d.ts index 5794a63..afd19b1 100644 --- a/dist/utils/log.d.ts +++ b/dist/utils/log.d.ts @@ -2,7 +2,7 @@ export declare const log: { info: (msg: string, log?: any) => void; success: (msg: string, log?: any) => void; error: (msg: string | Error, log?: any) => void; - warn: (msg: string) => void; + warn: (msg: string, log?: any) => void; build: (msg: string) => void; watch: (msg: string) => void; server: (url: string) => void; diff --git a/dist/utils/log.js b/dist/utils/log.js index cd038e9..3e89057 100644 --- a/dist/utils/log.js +++ b/dist/utils/log.js @@ -3,6 +3,7 @@ import AppNames from "./grab-app-names"; const prefix = { info: chalk.bgCyan.bold(" ℹnfo "), success: chalk.green.bold("✓"), + zap: chalk.green.bold("⚡"), error: chalk.red.bold("✗"), warn: chalk.yellow.bold("⚠"), build: chalk.magenta.bold("⚙"), @@ -16,7 +17,7 @@ export const log = { console.log(`${prefix.success} ${chalk.green(msg)}`, log || ""); }, error: (msg, log) => console.error(`${prefix.error} ${chalk.red(String(msg))}`, log || ""), - warn: (msg) => console.warn(`${prefix.warn} ${chalk.yellow(msg)}`), + warn: (msg, log) => console.warn(`${prefix.warn} ${chalk.yellow(msg)}`, log || ""), build: (msg) => console.log(`${prefix.build} ${chalk.magenta(msg)}`), watch: (msg) => console.log(`${prefix.watch} ${chalk.blue(msg)}`), server: (url) => console.log(`${prefix.success} ${chalk.white("Server running on")} ${chalk.cyan.underline(url)}`), diff --git a/dist/utils/rewrite-pages-module.js b/dist/utils/rewrite-pages-module.js index 4d6346d..16b7815 100644 --- a/dist/utils/rewrite-pages-module.js +++ b/dist/utils/rewrite-pages-module.js @@ -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"; export default async function rewritePagesModule(params) { const { page_file_path } = params || {}; let target_pages; @@ -15,17 +17,21 @@ export default async function rewritePagesModule(params) { } for (let i = 0; i < target_pages.length; i++) { const page_path = target_pages[i]; - const dst_path = pagePathTransform({ page_path }); - if (page_path.match(/__root\.tsx?/)) { - continue; - } - 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, - }); + await transformFile(page_path); + } + const { root_file_path } = grabRootFilePath(); + if (root_file_path && existsSync(root_file_path)) { + await transformFile(root_file_path); } } +async function transformFile(page_path) { + 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, + }); +} diff --git a/package.json b/package.json index 87cd562..dd8164e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@moduletrace/bunext", "module": "index.ts", "type": "module", - "version": "1.0.20", + "version": "1.0.3", "main": "dist/index.js", "types": "dist/index.d.ts", "exports": {