// @bun
// src/constants.ts
var SECONDS_IN_A_MINUTE = 60;
var MILLISECONDS_IN_A_SECOND = 1000;
var MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
var MINUTES_IN_AN_HOUR = 60;
var HOURS_IN_DAY = 24;
var MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
var TIME_PRECISION = 2;
var TWO_THIRDS = 2 / 3;
var DEFAULT_PORT = 3000;
// src/core/build.ts
import { rm, mkdir, writeFile as writeFile2 } from "fs/promises";
import { join, basename } from "path";
import { cwd, exit } from "process";
var {$, build: bunBuild, Glob: Glob2 } = globalThis.Bun;

// src/utils/updateScriptTags.ts
import { readFile, writeFile } from "fs/promises";
var {Glob } = globalThis.Bun;
var updateScriptTags = async (manifest, htmlDir) => {
  const glob = new Glob("*.html");
  const htmlFiles = [];
  const fileIterator = glob.scan({ absolute: true, cwd: htmlDir });
  for await (const filePath of fileIterator) {
    htmlFiles.push(filePath);
  }
  const tasks = htmlFiles.map(async (filePath) => {
    const original = await readFile(filePath, "utf8");
    const updated = Object.entries(manifest).reduce((html, [scriptName, newPath]) => {
      const esc = scriptName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
      const regex = new RegExp(`(<script[^>]+src=["'])(/?(?:.*/)?${esc})(?:\\.[^."'/]+)?(\\.js)(["'][^>]*>)`, "g");
      return html.replace(regex, (_, prefix, __, ___, suffix) => `${prefix}${newPath}${suffix}`);
    }, original);
    await writeFile(filePath, updated, "utf8");
  });
  await Promise.all(tasks);
};

// src/core/build.ts
var build = async ({
  buildDirectory = "build",
  assetsDirectory,
  reactDirectory,
  htmlDirectory,
  htmxDirectory,
  tailwind
}) => {
  const start = performance.now();
  const projectRoot = cwd();
  const buildDirectoryAbsolute = join(projectRoot, buildDirectory);
  const assetsDirectoryAbsolute = assetsDirectory && join(projectRoot, assetsDirectory);
  const reactIndexesDirectory = reactDirectory && join(projectRoot, reactDirectory, "indexes");
  const reactPagesDirectory = reactDirectory && join(projectRoot, reactDirectory, "pages");
  const htmlPagesDirectory = htmlDirectory && join(projectRoot, htmlDirectory, "pages");
  const htmlScriptsDirectory = htmlDirectory && join(projectRoot, htmlDirectory, "scripts");
  const htmxDirectoryAbsolute = htmxDirectory && join(projectRoot, htmxDirectory);
  await rm(buildDirectoryAbsolute, { force: true, recursive: true });
  await mkdir(buildDirectoryAbsolute);
  reactPagesDirectory && reactIndexesDirectory && await generateReactIndexFiles(reactPagesDirectory, reactIndexesDirectory);
  assetsDirectoryAbsolute && await $`cp -R ${assetsDirectoryAbsolute} ${buildDirectoryAbsolute}`;
  if (htmlPagesDirectory) {
    await mkdir(join(buildDirectoryAbsolute, "html", "pages"), {
      recursive: true
    });
    await $`cp -R ${htmlPagesDirectory} ${join(buildDirectoryAbsolute, "html")}`;
  }
  if (htmxDirectoryAbsolute) {
    await mkdir(join(buildDirectoryAbsolute, "htmx"));
    await $`cp -R ${htmxDirectoryAbsolute} ${join(buildDirectoryAbsolute)}`;
  }
  if (tailwind) {
    await $`bunx @tailwindcss/cli -i ${tailwind.input} -o ${join(buildDirectoryAbsolute, tailwind.output)}`;
  }
  const reactEntryPaths = reactIndexesDirectory && await scanEntryPoints(reactIndexesDirectory, "*.tsx");
  const htmlEntryPaths = htmlScriptsDirectory && await scanEntryPoints(htmlScriptsDirectory, "*.{js,ts}");
  const entryPaths = [...reactEntryPaths || [], ...htmlEntryPaths || []];
  if (entryPaths.length === 0) {
    console.warn("No entry points found, skipping building manifest");
    return null;
  }
  const { logs, outputs } = await bunBuild({
    entrypoints: entryPaths,
    format: "esm",
    naming: `[dir]/[name].[hash].[ext]`,
    outdir: buildDirectoryAbsolute,
    target: "bun"
  }).catch((error) => {
    console.error("Build failed:", error);
    exit(1);
  });
  logs.forEach((log) => {
    if (log.level === "error")
      console.error(log);
    else if (log.level === "warning")
      console.warn(log);
    else if (log.level === "info" || log.level === "debug")
      console.info(log);
  });
  const manifest = outputs.reduce((acc, artifact) => {
    let relativePath = artifact.path;
    if (relativePath.startsWith(buildDirectoryAbsolute)) {
      relativePath = relativePath.slice(buildDirectoryAbsolute.length);
    }
    relativePath = relativePath.replace(/^\/+/, "");
    const baseName = relativePath.split("/").pop();
    if (!baseName)
      return acc;
    const hashDelimiter = `.${artifact.hash}.`;
    if (!baseName.includes(hashDelimiter)) {
      throw new Error(`Expected hash delimiter ${hashDelimiter} in ${baseName}`);
    }
    const [fileName] = baseName.split(hashDelimiter);
    acc[fileName] = `/${relativePath}`;
    return acc;
  }, {});
  htmlPagesDirectory && await updateScriptTags(manifest, join(buildDirectoryAbsolute, "html", "pages"));
  const end = performance.now();
  const durationMs = end - start;
  let duration;
  if (durationMs < MILLISECONDS_IN_A_SECOND) {
    duration = `${durationMs.toFixed(TIME_PRECISION)}ms`;
  } else if (durationMs < MILLISECONDS_IN_A_MINUTE) {
    duration = `${(durationMs / MILLISECONDS_IN_A_SECOND).toFixed(TIME_PRECISION)}s`;
  } else {
    duration = `${(durationMs / MILLISECONDS_IN_A_MINUTE).toFixed(TIME_PRECISION)}m`;
  }
  console.log(`Build completed in ${duration}`);
  return manifest;
};
var generateReactIndexFiles = async (reactPagesDirectory, reactIndexesDirectory) => {
  await rm(reactIndexesDirectory, { force: true, recursive: true });
  await mkdir(reactIndexesDirectory);
  const pagesGlob = new Glob2("*.*");
  const files = [];
  for await (const file of pagesGlob.scan({ cwd: reactPagesDirectory })) {
    files.push(file);
  }
  const promises = files.map(async (file) => {
    const fileName = basename(file);
    const [componentName] = fileName.split(".");
    const content = [
      `import { hydrateRoot } from 'react-dom/client';`,
      `import type { ComponentType } from 'react'`,
      `import { ${componentName} } from '../pages/${componentName}';
`,
      `type PropsOf<C> = C extends ComponentType<infer P> ? P : never;
`,
      `declare global {`,
      `	interface Window {`,
      `		__INITIAL_PROPS__: PropsOf<typeof ${componentName}>`,
      `	}`,
      `}
`,
      `hydrateRoot(document, <${componentName} {...window.__INITIAL_PROPS__} />);`
    ].join(`
`);
    return writeFile2(join(reactIndexesDirectory, `${componentName}Index.tsx`), content);
  });
  await Promise.all(promises);
};
var scanEntryPoints = async (dir, pattern) => {
  const entryPaths = [];
  const glob = new Glob2(pattern);
  for await (const file of glob.scan({ absolute: true, cwd: dir })) {
    entryPaths.push(file);
  }
  return entryPaths;
};
// src/core/pageHandlers.ts
var {file } = globalThis.Bun;
import { createElement } from "react";
import { renderToReadableStream } from "react-dom/server";
var handleReactPageRequest = async (pageComponent, index, ...props) => {
  const [maybeProps] = props;
  const element = maybeProps !== undefined ? createElement(pageComponent, maybeProps) : createElement(pageComponent);
  const stream = await renderToReadableStream(element, {
    bootstrapModules: [index],
    bootstrapScriptContent: maybeProps ? `window.__INITIAL_PROPS__=${JSON.stringify(maybeProps)}` : undefined
  });
  return new Response(stream, {
    headers: { "Content-Type": "text/html" }
  });
};
var handleHTMLPageRequest = (html) => file(html);
// src/plugins/networkingPlugin.ts
import { argv } from "process";
var {env } = globalThis.Bun;

// src/utils/networking.ts
import os from "os";
var getLocalIPAddress = () => {
  const interfaces = os.networkInterfaces();
  const addresses = Object.values(interfaces).flat().filter((iface) => iface !== undefined);
  const ipAddress = addresses.find((iface) => iface.family === "IPv4" && !iface.internal);
  if (ipAddress)
    return ipAddress.address;
  console.warn("No IP address found, falling back to localhost");
  return "localhost";
};

// src/plugins/networkingPlugin.ts
var host = env.HOST ?? "localhost";
var port = env.PORT ?? DEFAULT_PORT;
var localIP;
var args = argv;
var hostFlag = args.includes("--host");
if (hostFlag) {
  localIP = getLocalIPAddress();
  host = "0.0.0.0";
}
var networkingPlugin = (app) => app.listen({
  hostname: host,
  port
}, () => {
  if (hostFlag) {
    console.log(`Server started on http://localhost:${port}`);
    console.log(`Server started on network: http://${localIP}:${port}`);
  } else {
    console.log(`Server started on http://${host}:${port}`);
  }
});
// src/plugins/pageRouterPlugin.ts
var pageRouterPlugin = () => {
  console.log("Page Router Plugin Not Implemented Yet");
};
export {
  updateScriptTags,
  pageRouterPlugin,
  networkingPlugin,
  handleReactPageRequest,
  handleHTMLPageRequest,
  getLocalIPAddress,
  build,
  TWO_THIRDS,
  TIME_PRECISION,
  SECONDS_IN_A_MINUTE,
  MINUTES_IN_AN_HOUR,
  MILLISECONDS_IN_A_SECOND,
  MILLISECONDS_IN_A_MINUTE,
  MILLISECONDS_IN_A_DAY,
  HOURS_IN_DAY,
  DEFAULT_PORT
};

//# debugId=0994B2A81D48437664756E2164756E21
//# sourceMappingURL=index.js.map
